python-hpilo-3.6/0000755000175000017500000000000012652734620014605 5ustar dennisdennis00000000000000python-hpilo-3.6/hpilo_fw.py0000644000175000017500000000722412652734620016773 0ustar dennisdennis00000000000000# Downloader / extracter for latest iLO2 / iLO3 / iLO4 firmware # # (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details import tarfile import os import sys PY3 = sys.version_info[0] >= 3 if PY3: import urllib.request as urllib2 import configparser as ConfigParser from io import BytesIO, StringIO b = lambda x: bytes(x, 'ascii') GZIP_CONSTANT = '\x1f\x8b'.encode('latin-1') else: import urllib2 import ConfigParser from cStringIO import StringIO as StringIO BytesIO = StringIO b = lambda x: x GZIP_CONSTANT = '\x1f\x8b' _config = None def config(mirror=None): global _config if not _config: if mirror: conf = _download(mirror + 'firmware.conf') else: conf = _download('https://raw.githubusercontent.com/seveas/python-hpilo/master/firmware.conf') if PY3: conf = conf.decode('ascii') parser = ConfigParser.ConfigParser() parser.readfp(StringIO(conf)) _config = {} for section in parser.sections(): _config[section] = {} for option in parser.options(section): _config[section][option] = parser.get(section, option) if mirror: for section in _config: _config[section]['url'] = mirror + _config[section]['file'] return _config def download(ilo, path=None, progress = lambda txt: None): if not path: path = os.getcwd() conf = config() if not os.path.exists(os.path.join(path, conf[ilo]['file'])): msg = "Downloading %s firmware version %s" % (ilo.split()[0], conf[ilo]['version']) progress(msg) data = _download(conf[ilo]['url'], lambda txt: progress('%s %s' % (msg, txt))) if conf[ilo]['url'].endswith('.bin'): fd = open(os.path.join(path, conf[ilo]['file']), 'w') fd.write(data) fd.close() else: _parse(data, path, conf[ilo]['file']) return True return False def parse(fwfile, ilo): fd = open(fwfile) data = fd.read() fd.close() if '_SKIP=' in data: # scexe file fwfile = _parse(data, os.getcwd()) return fwfile def _download(url, progress=lambda txt: None): req = urllib2.urlopen(url) size = int(req.headers['Content-Length']) if size < 16384: return req.read() downloaded = 0 data = b('') while downloaded < size: new = req.read(16384) data += new downloaded += len(new) progress('%d/%d bytes (%d%%)' % (downloaded, size, downloaded*100.0/size)) sys.stdout.flush() return data def _parse(scexe, path, filename=None): # An scexe is a shell script with an embedded compressed tarball. Find the tarball. skip_start = scexe.index(b('_SKIP=')) + 6 skip_end = scexe.index(b('\n'), skip_start) skip = int(scexe[skip_start:skip_end]) - 1 tarball = scexe.split(b('\n'), skip)[-1] # Now uncompress it if tarball[:2] != GZIP_CONSTANT: raise ValueError("scexe file seems corrupt") tf = tarfile.open(name="bogus_name_for_old_python_versions", fileobj=BytesIO(tarball), mode='r:gz') filenames = [x for x in tf.getnames() if x.endswith('.bin')] orig_filename = filename if not filename or filename not in filenames: if len(filenames) != 1: raise ValueError("scexe file seems corrupt") if filename and filename.lower() != filenames[0].lower(): raise ValueError("scexe file seems corrupt") filename = filenames[0] tf.extract(filename, path) if filename != filename.lower(): os.rename(filename, filename.lower()) return filename.lower() python-hpilo-3.6/hpilo_cli0000755000175000017500000002716112652734620016504 0ustar dennisdennis00000000000000#!/usr/bin/python # # (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details try: import ConfigParser except ImportError: import configparser as ConfigParser try: basestring except NameError: basestring = str import hpilo import hpilo_fw try: input = raw_input except NameError: pass import getpass import optparse import os from pprint import pprint import sys import urllib2 ilo_methods = sorted([x for x in dir(hpilo.Ilo) if not x.startswith('_') and x.islower()]) def main(): usage = """ %prog [options] hostname method [args...] [ + method [args...]...] %prog download_rib_firmware ilotype version [version...] """ p = optparse.OptionParser(usage=usage, add_help_option=False) p.add_option("-l", "--login", dest="login", default=None, help="Username to access the iLO") p.add_option("-p", "--password", dest="password", default=None, help="Password to access the iLO") p.add_option("-i", "--interactive", action="store_true", default=False, help="Prompt for username and/or password if they are not specified.") p.add_option("-c", "--config", dest="config", default="~/.ilo.conf", help="File containing authentication and config details", metavar="FILE") p.add_option("-t", "--timeout", dest="timeout", type="int", default=60, help="Timeout for iLO connections") p.add_option("-j", "--json", dest="format", action="store_const", const="json", default="python", help="Output a json document instead of a python dict") p.add_option("-y", "--yaml", dest="format", action="store_const", const="yaml", default="python", help="Output a yaml document instead of a python dict") p.add_option("-P", "--protocol", dest="protocol", choices=("http","raw","local"), default=None, help="Use the specified protocol instead of autodetecting") p.add_option("-d", "--debug", dest="debug", action="count", default=0, help="Output debug information, repeat to see all XML data") p.add_option("-o", "--port", dest="port", type="int", default=443, help="SSL port to connect to") p.add_option("-h", "--help", action="callback", callback=hpilo_help, help="show this help message or help for a method") p.add_option("-H", "--help-methods", action="callback", callback=hpilo_help_methods, help="show all supported methods") p.add_option('--save-response', dest="save_response", default=None, metavar='FILE', help="Store XML output in this file") p.add_option('--read-response', dest="read_response", default=None, metavar='FILE', help="Read XML response from this file instead of the iLO") p.add_option('-v', '--version', action="callback", callback=hpilo_version) opts, args = p.parse_args() if opts.format == 'json': import json elif opts.format == 'yaml': import yaml # Did we get correct arguments? if len(args) < 2: p.error("Not enough arguments") if args[1] not in ilo_methods and args[0] != 'download_rib_firmware': p.error("Unknown method: %s" % args[1]) config = ConfigParser.ConfigParser() if os.path.exists(os.path.expanduser(opts.config)): config.read(os.path.expanduser(opts.config)) if args[0] == 'download_rib_firmware': if config.has_option('firmware', 'mirror'): hpilo_fw.config(mirror=config.get('firmware', 'mirror')) return download(args[1], args[2:]) hostname = args.pop(0) args_ = list_split(args, '+') calls = [] for args in args_: method = args.pop(0) # Arguments must be passed as param=value pairs that are valid arguments to the methods if sys.version_info[0] >= 3: func = getattr(hpilo.Ilo, method)#.__func__ argnames = func.__code__.co_varnames[1:func.__code__.co_argcount] args_with_defaults = [] if func.__defaults__: args_with_defaults = argnames[-len(func.__defaults__):] else: func = getattr(hpilo.Ilo, method).im_func argnames = func.func_code.co_varnames[1:func.func_code.co_argcount] args_with_defaults = [] if func.func_defaults: args_with_defaults = argnames[-len(func.func_defaults):] params = {} for arg in args: if '=' not in arg: hpilo_help(None, None, method, None, 2) param, val = arg.split('=', 1) # Do we expect structured data? keys = param.split('.') if (len(keys) > 1) != (keys[0] in getattr(func, 'requires_dict', {})): hpilo_help(None, None, method, None, 2) if keys[0] not in argnames: hpilo_help(None, None, method, None, 2) # Optionally extract values from the config if val.startswith('$') and '.' in val: section, option = val[1:].split('.', 1) if config.has_option(section, option): val = config.get(section, option) # Do some type coercion for shell goodness if val.isdigit(): val = int(val) else: val = {'true': True, 'false': False}.get(val.lower(), val) params_ = params for key in keys[:-1]: if key not in params_: params_[key] = {} params_ = params_[key] params_[keys[-1]] = val for name in argnames: if name not in params and name not in args_with_defaults: hpilo_help(None, None, method, None, 2) calls.append((method, params)) # Do we have login information login = None password = None needs_login = bool(opts.read_response) for m, _ in calls: if m != 'xmldata': needs_login = True break if hostname == 'localhost': opts.protocol = 'local' needs_login = False if needs_login: if config.has_option('ilo', 'login'): login = config.get('ilo', 'login') if config.has_option('ilo', 'password'): password = config.get('ilo', 'password') if opts.login: login = opts.login if opts.password: password = opts.password if not login or not password: if opts.interactive: while not login: login = input('Login for iLO at %s: ' % hostname) while not password: password = getpass.getpass('Password for %s@%s:' % (login, hostname)) else: p.error("No login details provided") opts.protocol = { 'http': hpilo.ILO_HTTP, 'raw': hpilo.ILO_RAW, 'local': hpilo.ILO_LOCAL, }.get(opts.protocol, None) ilo = hpilo.Ilo(hostname, login, password, opts.timeout, opts.port, opts.protocol, len(calls) > 1) ilo.debug = opts.debug ilo.save_response = opts.save_response ilo.read_response = opts.read_response if config.has_option('ilo', 'hponcfg'): ilo.hponcfg = config.get('ilo', 'hponcfg') if config.has_option('firmware', 'mirror'): ilo.firmware_mirror = config.get('firmware', 'mirror') def _q(val): if isinstance(val, basestring): return '"%s"' % val.replace("\\","\\\\").replace('"','\\"') else: return str(val) for method, params in calls: if method == 'update_rib_firmware': params['progress'] = print_progress results = [getattr(ilo, method)(**params)] if 'progress' in params: params.pop('progress')("") if len(calls) > 1: results = ilo.call_delayed() if opts.format == 'json': if len(calls) == 1: results = results[0] json.dump(results, sys.stdout) elif opts.format == 'yaml': yaml.dump(results, sys.stdout) else: for method, params in calls: param_str = ', '.join(["%s=%s" % (x[0], _q(x[1])) for x in params.items()]) if method.startswith('get') or method == 'certificate_signing_request' or len(calls) == 1: result = results.pop(0) else: result = None if isinstance(result, basestring): print(">>> print(my_ilo.%s(%s))" % (method, param_str)) print(result) elif result is None: print(">>> my_ilo.%s(%s)" % (method, param_str)) else: print(">>> pprint(my_ilo.%s(%s))" % (method, param_str)) pprint(result) def hpilo_help(option, opt_str, value, parser, exitcode=0): if not value: if parser and parser.rargs and parser.rargs[0][0] != '-': value = parser.rargs[0] del parser.rargs[0] if not value: parser.print_help() else: if value in ilo_methods: import re, textwrap func = getattr(hpilo.Ilo, value).im_func code = func.func_code args = '' if code.co_argcount > 1: args = code.co_varnames[:code.co_argcount] defaults = func.func_defaults or [] args = ["%s=%s" % (x, x.upper()) for x in args[:len(args)-len(defaults)]] + \ ["[%s=%s]" % (x,str(y)) for x, y in zip(args[len(args)-len(defaults):], defaults) if x != 'progress'] args = ' ' + ' '.join(args[1:]) print(textwrap.fill("Ilo.%s%s:" % (value, args), 80)) doc = getattr(hpilo.Ilo, value).__doc__ or "No documentation" doc = re.sub(r':[a-z]+:`(.*?)`', r'\1', doc) if 'API note' in doc: doc = doc[:doc.find('API note')].strip() doc = re.sub('\s+', ' ', doc) print(textwrap.fill(doc, 80)) else: print("No such method: %s" % value) if parser: parser.exit(exitcode) else: sys.exit(exitcode) def hpilo_help_methods(option, opt_str, value, parser): print("""Supported methods: - %s""" % "\n- ".join(ilo_methods)) parser.exit() def hpilo_version(option, opt_str, value, parser): print(hpilo.__version__) sys.exit() def print_progress(text): sys.stdout.write('\r\033[K' + text) sys.stdout.flush() def list_split(lst, sep): ret = [] while True: try: pos = lst.index(sep) except ValueError: ret.append(lst) break ret.append(lst[:pos]) lst = lst[pos+1:] return ret def download(ilotype, versions): ilotype = ilotype.lower() config = hpilo_fw.config() if ilotype == 'all': for ilotype in sorted(config.keys()): if (versions == ['all']) == (' ' in ilotype): _download(config, ilotype) else: if not versions: _download(config, ilotype) elif versions == ['all']: for key in sorted(config.keys()): if key.startswith(ilotype + ' '): _download(config, key) else: for version in versions: _download(config, '%s %s' % (ilotype, version)) def _download(config, key): if key not in config: sys.stderr.write("Unkown ilo/firmware version: %s\n" % key) sys.exit(1) try: if hpilo_fw.download(key, progress=print_progress): print("") else: print("%s firmware version %s was already downloaded" % (key.split()[0], config[key]['version'])) except urllib2.HTTPError: e = sys.exc_info()[1] print("\n%s" % str(e)) if __name__ == '__main__': main() python-hpilo-3.6/COPYING0000644000175000017500000000144712652734620015646 0ustar dennisdennis00000000000000python-hpilo - Manage iLO interfaces from python code Copyright (C) 2011-2016 Dennis Kaarsemaker This program is free software: you can redistribute it and/or modify it under the terms of (at your option) either the Apache License, Version 2.0, or 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. This program 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. For details and specific language governing permissions and limitations, see either - http://www.gnu.org/licenses/ for the GNU GPL - http://www.apache.org/licenses/LICENSE-2.0 for the Apache license python-hpilo-3.6/CHANGES0000644000175000017500000001261312652734620015603 0ustar dennisdennis00000000000000Version 3.6, 2016-01-29 * Actually fix mod_snmp_im_settings' cpability of setting ro/trap communities Version 3.5, 2016-01-29 * Restore python 2.4 compatibility, which broke in 3.0 Version 3.4, 2015-12-20 * Bugfixes in set_ers_direct_connect and get_persistent_boot * xmldata now also supports querying for license keys Version 3.3, 2015-10-14 * A puppet module has been added * More error codes get their own exception classes * Passing incorrect arguments to hpilo_cli now causes it to consistently exit with a nonzero exitcode * A bug in dealing with SSL errors was fixed * When saving responses retrieved using the ILO_LOCAL protocol, the garbage data added by hponcfg is now properly removed Version 3.2, 2015-10-11 * When reading responses saved earlier, the protocol is now detected properly * A new testsuite has been written * Various bugs were fixed * More error codes get their own exception classes Version 3.1, 2015-10-06 * hpilo_ca now creates sha256 signatures * hpilo_ca now includes the localityName in certificates Version 3.0, 2015-10-05 * Major version bump as we're now dual licensed under GPL 3+ and APL at HP's request, mainly for using hpilo.py with OpenStack * Add more example applications: an elasticsearch importer and an automatic firmware updater * Modernize the hpilo_ca example * hpilo_cli now understands --version, and hpilo.py has a __version__ attribute * All development tools are moved to a subdir * SSL certificate errors are now ignored under python 2.7.9+ and 3.5+ as well * Add 'download_rib_firmware all all' to create a firmware mirror Version 2.13, 2015-04-13 * We will now find hponcfg on you $PATH * Major documentation overhaul * hpilo_ca has been moved to examples/ * the xmldata can now also be used to query chassis onboard administrators * get_persistent_boot bow supports uEFI booting Version 2.12, 2015-04-07 * Proliant gen9 compatibility fixes * Fix to trapcommunity parameters in mod_snmp_im_settings * Don't ask for login data when they are not needed * Ignore ENOTCONN when closing connections * Support local firmware mirrors Version 2.11, 2015-01-12 * set_server_name now works around a bug in some iLO versions Version 2.10, 2014-12-21 * Fixes to get_embedded_health * Restore python 2.4 compatibility Version 2.9, 2014-10-18 * Work around an iLO bug in the get_embedded_health output * Bugfix in certificate_signing_request Version 2.8, 2014-08-08 * Adds several new functions for iLO4 support Version 2.7, 2014-07-23 * update_rib_firmware now accepts firmware version numbers and will install the specified version * xmldata now respects timeouts and refuses to use a proxy * Several small bugfixes Backward incompatibility note: update_rib_firmware accepts a callback that gets called with progress updates. The messages this callback gets have been simplified an no longer contain LF or ANSI characters, all responsibility for correct presentation now lies with the progress callback. Version 2.6.2, 2014-06-16 * Deal with backwards incompatibility in import_ssh_key Version 2.6.1, 2014-04-16 * Brown paper bag release, 2.6 did not update the version Version 2.6, 2014-04-16 * Add an xmldata call, which is not actually using the XML api but parses what a request to /xmldata?item=all returns. * Support for structured arguments in the command-line tool * Several bugfixes and new calls and new arguments to existing calls Version 2.5, 2013-11-28 * hponcfg can update firmware, so make the ILO_LOCAL support in hpilo.py support this as well Version 2.4.2, 2013-11-11 * hpilo_ca supports ilo4+ as well Version 2.4.1, 2013-11-06 * Bugfix in mod_network_settings Version 2.4, 2013-10-27 * Much better ipv6 support Version 2.3, 2013-10-11 * Many more functions that were introduced with more recent versions of iLO and with firmware updates Version 2.2, 2013-09-17 * Clearer errors when calling unsupported funcrions * Support for YAML output * Support for older SSL versions Version 2.1, 2013-02-06 * More useful get_embedded_health for iLO3 and iLO4 * Several bugs fixed * Test framwwork fixes Version 2.0.1, 2013-01-05 * Fixes several regressions in 2.0 Version 2.0, 2012-12-24 * Add a delayed call function so you can call multiple functions in one connection, speeding up total functionality * Add mod_dir_config * Add callback functionality and clean up code by using them Version 1.5, 2012-11-08 * Add a small test suite * Fixes several bugs * hpilo_cli now asks for a username/password if they're now given * More consistent get_one_time_boot output Version 1.4.1, 2012-09-08 * Packaging fixes Version 1.4, 2012-09-04 * Improved documentation * Be compatible with more python versions Version 1.3, 2012-08-28 * iLO 4 support * More python 3 compatibility * Now includes autoatic latest firmware downloader * Can now talk to the iLO via hponcfg instead of the network Version 1.2, 2012-06-07 * Python 3 compatibility * Don't break base64 data while working around an HP bug * Fixes for import_ssh_key Version 1.1, 2012-03-31 * Handle TLSv1 connections Version 1.0, 2012-03-10 * Adds certificate handling and a mini-CA * Improved documentation * Cleanup in some functions Version 0.5, 2012-03-09 * Add firmware update functionality * More functions added * Backwards incompatible change in some methods to stick to HP's XML tag names * More useful --help output and error messages Version 0.2, 2012-03-01 * Initial public release, older versions were internal-only python-hpilo-3.6/README.md0000644000175000017500000000462312652734620016071 0ustar dennisdennis00000000000000iLO automation from python or shell =================================== HP servers come with a powerful out of band management interface called Integrated Lights out, or iLO. It has an extensive web interface and commercially available tools for centrally managing iLO devices and their servers. But if you want to built your own tooling, integrate iLO management to your existing procedures or simply want to manage iLOs using a command-line interface, you're stuck manually creating XML files and using a perl hack HP ships called locfg.pl. Enter python-hpilo! Using the same XML interface as HP's own management tools, here is a python library and command-line tool that make it a lot easier to do all the above. No manual XML writing, just call functions from either python or your shell(script). Usage ----- Full usage documentation can be found on http://seveas.github.io/python-hpilo/ or in the docs/ directory in the python-hpilo tarball. Here are some examples to wet your appetite: Getting the chassis IP of a blade server, from python: >>> ilo = hpilo.Ilo('example-server.int.kaarsemaker.net') >>> chassis = ilo.get_oa_info() >>> print chassis['ipaddress'] 10.42.128.101 Entering a license key and creating a user, from the shell: $ hpilo_cli example-server.int.kaarsemaker.net activate_license key=$mykey $ hpilo_cli example-server.int.kaarsemaker.net add_user user_login=dennis \ password=hunter2 admin_priv=true Compatibility ------------- This module is written with compatibility as main priority. Currently supported are: * All RILOE II/iLO versions up to and including iLO 4 * Python 2.4-2.7 and python 3.2 and newer * Any operating system Python runs on iLOs can be managed both locally using `hponcfg` or remotely using the iLO's built-in webserver. In the latter case, the requirements above concern the machine you run this code on, not the managed server. Author and license ------------------ This software is (c) 2011-2014 Dennis Kaarsemaker This program 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. HP, Integrated Lights out and iLO are trademarks of HP, with whom the author of this software is not affiliated in any way other than using some of their hardware. python-hpilo-3.6/examples/0000755000175000017500000000000012652734620016423 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/ca/0000755000175000017500000000000012652734620017006 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/ca/hpilo_ca0000755000175000017500000002672612652734620020527 0ustar dennisdennis00000000000000#!/usr/bin/python # # (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details try: import ConfigParser except ImportError: import configparser as ConfigParser import hpilo import optparse import os import re import subprocess import sys import time def main(): usage = """%prog [options] init %prog [options] sign hostname [hostname ...]""" p = optparse.OptionParser(usage=usage) p.add_option("-l", "--login", dest="login", default=None, help="Username to access the iLO") p.add_option("-p", "--password", dest="password", default=None, help="Password to access the iLO") p.add_option("-c", "--config", dest="config", default="~/.ilo.conf", help="File containing authentication and config details", metavar="FILE") p.add_option("-t", "--timeout", dest="timeout", type="int", default=60, help="Timeout for iLO connections") p.add_option("-P", "--protocol", dest="protocol", choices=("http","raw"), default=None, help="Use the specified protocol instead of autodetecting") p.add_option("-d", "--debug", dest="debug", action="count", default=0, help="Output debug information, repeat to see all XML data") p.add_option("-o", "--port", dest="port", type="int", default=443, help="SSL port to connect to") p.add_option("-s", "--openssl", dest="openssl_bin", default="/usr/bin/openssl", help="Path to the openssl binary") p.add_option("-u", "--upgrade", dest="upgrade", action="store_true", default=False, help="Upgrade iLO firmware that is too old automatically") opts, args = p.parse_args() if not args or args[0] not in ('init','sign'): p.print_help() p.exit(1) if not os.path.exists(os.path.expanduser(opts.config)): p.error("Configuration file '%s' does not exist" % opts.config) config = ConfigParser.ConfigParser() config.read(os.path.expanduser(opts.config)) if not config.has_option('ca', 'path'): p.error("No CA path specified in the config") ca_path = os.path.expanduser(config.get('ca', 'path')) os.environ['CA_PATH'] = ca_path os.environ['SUBJECTALTNAME'] = '' csr_params = {} for key in ('country', 'state', 'locality', 'organization', 'organizational_unit'): if config.has_option('ca', key): csr_params[key] = config.get('ca', key) openssl = OpenSSL(opts.openssl_bin, ca_path, csr_params) if args[0] == 'init': if len(args) > 2: p.error("Too many arguments") openssl.init_ca() sys.exit(0) # Do we have login information login = None password = None if config.has_option('ilo', 'login'): login = config.get('ilo', 'login') if config.has_option('ilo', 'password'): password = config.get('ilo', 'password') if opts.login: login = opts.login if opts.password: password = opts.password if not login or not password: p.error("No login details provided") todo = args[1:] for host in args[1:]: if re.match(r'\d+(\.\d+){3}', host): p.error("hpilo_ca only accepts fqdns, not IP addresses") if '.' not in host: p.error("hpilo_ca only accepts fqdns, not hostnames") while todo: todo = sign_certificates(todo, openssl, login, password, opts) if todo: print("Waiting a minute before trying %d hosts again" % len(todo)) what = "\|/-" for i in range(60): sys.stdout.write("\r%s %-2d" % (what[i%4], 60-i)) sys.stdout.flush() time.sleep(1) sys.stdout.write("\r \r") sys.stdout.flush() def sign_certificates(hosts, openssl, login, password, opts): todo = [] for hostname in hosts: if openssl.signed(hostname): print("Certificate already signed, skipping") continue ilo = hpilo.Ilo(hostname, login, password, opts.timeout, opts.port) ilo.debug = opts.debug if opts.protocol == 'http': ilo.protocol = hpilo.ILO_HTTP elif opts.protocol == 'raw': ilo.protocol = hpilo.ILO_RAW print("(1/5) Checking certificate config of %s" % hostname) fw_version = ilo.get_fw_version() network_settings = ilo.get_network_settings() if fw_version['management_processor'].lower() == 'ilo2': version = fw_version['firmware_version'] if version < '2.06': print("iLO2 firmware version %s is too old" % version) if not opts.upgrade: print("Please upgrade firmware to 2.06 or newer") continue print("Upgrading iLO firmware") ilo.update_rib_firmware(version='latest', progress=print_progress) todo.append(hostname) continue cn = ilo.get_cert_subject_info()['csr_subject_common_name'] if '.' not in cn: ilo.cert_fqdn(use_fqdn=True) cn = ilo.get_cert_subject_info()['csr_subject_common_name'] hn, dn = hostname.split('.', 1) if network_settings['dns_name'] != hn or dn and network_settings['domain_name'] != dn: print("Hostname misconfigured on the ilo, fixing") ilo.mod_network_settings(dns_name=hn, domain_name=dn) todo.append(hostname) continue print("(2/5) Retrieving certificate signing request") if fw_version['management_processor'].lower() == 'ilo2': csr = ilo.certificate_signing_request() else: params = openssl.csr_params.copy() cn = '%s.%s' % (network_settings['dns_name'], network_settings['domain_name']) params['common_name'] = cn try: csr = ilo.certificate_signing_request(**params) except hpilo.IloGeneratingCSR: print("Certificate request is being generated, trying again later") todo.append(hostname) continue if not csr: print("Received an empty CSR") continue print("(3/5) Signing certificate") cert = openssl.sign(network_settings, csr) print("(4/5) Uploading certificate") ilo.import_certificate(cert) print("(5/5) Resetting iLO") ilo.reset_rib() return todo class OpenSSL(object): def __init__(self, openssl_bin, ca_path, csr_params): self.openssl_bin = openssl_bin self.ca_path = ca_path self.openssl_cnf = os.path.join(ca_path, 'openssl.cnf') self.csr_params = csr_params def call(self, *args, **envvars): env = os.environ.copy() env.update(envvars) args = list(args) if args[0] in ('req', 'ca'): args = args[:1] + ['-config', self.openssl_cnf] + args[1:] return subprocess.call([self.openssl_bin] + args, env=env) def signed(self, hostname): crt_path = os.path.join(self.ca_path, 'certs', hostname + '.crt') return os.path.exists(crt_path) def sign(self, network_settings, csr): hostname = network_settings['dns_name'] fqdn = '%s.%s' % (network_settings['dns_name'], network_settings['domain_name']) ip = network_settings['ip_address'] altnames = 'DNS:%s,DNS:%s,IP:%s' % (fqdn, hostname, ip) csr_path = os.path.join(self.ca_path, 'certs', hostname + '.csr') crt_path = os.path.join(self.ca_path, 'certs', hostname + '.crt') fd = open(csr_path, 'w') fd.write(csr) fd.close() self.call('ca', '-batch', '-in', csr_path, '-out', crt_path, SUBJECTALTNAME=altnames) fd = open(crt_path) cert = fd.read() fd.close() cert = cert[cert.find('-----BEGIN'):] return cert def init_ca(self): if not os.path.exists(self.ca_path): os.makedirs(self.ca_path) if not os.path.exists(self.openssl_cnf): open(self.openssl_cnf, 'w').write(self.default_openssl_cnf) for dir in ('ca', 'certs', 'crl', 'archive'): if not os.path.exists(os.path.join(self.ca_path, dir)): os.mkdir(os.path.join(self.ca_path, dir)) if not os.path.exists(os.path.join(self.ca_path, 'archive', 'index')): open(os.path.join(self.ca_path, 'archive', 'index'),'w').close() if not os.path.exists(os.path.join(self.ca_path, 'archive', 'serial')): fd = open(os.path.join(self.ca_path, 'archive', 'serial'),'w') fd.write("00\n") fd.close() if not os.path.exists(os.path.join(self.ca_path, 'ca', 'hpilo_ca.key')): self.call('genrsa', '-out', os.path.join(self.ca_path, 'ca', 'hpilo_ca.key'), '2048') if not os.path.exists(os.path.join(self.ca_path, 'ca', 'hpilo_ca.crt')): self.call('req', '-new', '-x509', '-days', '7300', # 20 years should be enough for everyone :-) '-key', os.path.join(self.ca_path, 'ca', 'hpilo_ca.key'), '-out', os.path.join(self.ca_path, 'ca', 'hpilo_ca.crt')) default_openssl_cnf = """default_ca = hpilo_ca [hpilo_ca] dir = $ENV::CA_PATH certs = $dir/certs crl_dir = $dir/crl private_key = $dir/ca/hpilo_ca.key certificate = $dir/ca/hpilo_ca.crt database = $dir/archive/index new_certs_dir = $dir/archive serial = $dir/archive/serial crlnumber = $dir/crl/crlnumber crl = $dir/crl/crl.pem RANDFILE = $dir/.rand x509_extensions = usr_cert name_opt = ca_default cert_opt = ca_default default_days = 1825 # 5 years default_crl_days = 30 default_md = sha256 preserve = no policy = req_policy [req_policy] countryName = supplied stateOrProvinceName = supplied localityName = supplied organizationName = supplied organizationalUnitName = optional commonName = supplied emailAddress = optional [req] dir = $ENV::CA_PATH default_bits = 2048 default_md = sha256 default_keyfile = $dir/ca/hpilo_ca.key distinguished_name = req_distinguished_name x509_extensions = ca_cert # The extentions to add to the self signed cert string_mask = MASK:0x2002 [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = NL countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Flevoland localityName = Locality Name (eg, city) localityName_default = Lelystad 0.organizationName = Organization Name (eg, company) 0.organizationName_default = Kaarsemaker.net commonName = Common Name (eg, your name or your server's hostname) commonName_max = 64 commonName_default = hpilo_ca [usr_cert] basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer nsComment = "Certificate generated by iLO CA" subjectAltName = $ENV::SUBJECTALTNAME [ca_cert] basicConstraints = CA:true subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always nsComment = "Certificate generated by iLO CA" """ def print_progress(text): if text.startswith('\r'): sys.stdout.write(text) sys.stdout.flush() else: print(text) if __name__ == '__main__': main() python-hpilo-3.6/examples/puppet/0000755000175000017500000000000012652734620017740 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/0000755000175000017500000000000012652734620021410 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/0000755000175000017500000000000012652734620022173 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/templates/0000755000175000017500000000000012652734620024171 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/templates/ilo-device.erb0000644000175000017500000000013312652734620026700 0ustar dennisdennis00000000000000<% require 'uri' uri = URI.parse(name) -%> [<%= uri.host %>] type ilo url <%= uri.to_s %> python-hpilo-3.6/examples/puppet/modules/ilo/manifests/0000755000175000017500000000000012652734620024164 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/manifests/init.pp0000644000175000017500000000071212652734620025470 0ustar dennisdennis00000000000000class ilo::proxy($devices) { package{['ruby-json', 'python-hpilo']: ensure => latest, } concat{"/etc/puppet/device.conf": ensure => present, mode => 400, owner => root, group => root, } device{$devices:} define device() { concat::fragment{"ilo-device-$name": target => "/etc/puppet/device.conf", content => template("ilo/ilo-device.erb") } } } python-hpilo-3.6/examples/puppet/modules/ilo/lib/0000755000175000017500000000000012652734620022741 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/0000755000175000017500000000000012652734620024256 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/0000755000175000017500000000000012652734620025233 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/network_device/0000755000175000017500000000000012652734620030243 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/network_device/ilo/0000755000175000017500000000000012652734620031026 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/network_device/ilo/transport.rb0000644000175000017500000000756312652734620033422 0ustar dennisdennis00000000000000require 'json' require 'puppet/provider/ilo' module Puppet::Util::NetworkDevice::Ilo class Transport attr_reader :hostname def initialize(hostname, local) @hostname = hostname @local = local @provider = Puppet::Provider::Ilo.new(hostname) @provider.mkcommands @cachedir = File.join(Puppet[:confdir], 'cache') Dir.mkdir(@cachedir) unless File.exist?(@cachedir) @cachable = { 'get_fw_version' => { :updaters => ['update_rib_firmware'], :ttl => 86400 * 3, }, 'get_global_settings' => { :updaters => ['mod_global_settings'], :ttl => 86400 * 2, }, 'get_network_settings' => { :updaters => ['mod_network_settings'], :ttl => 86400, }, 'get_all_licenses' => { :updaters => ['activate_license'], :ttl => 86400 * 4, }, 'get_dir_config' => { :updaters => ['mod_dir_config'], :ttl => 86400, }, 'get_snmp_im_settings' => { :updaters => ['mod_snmp_im_settings'], :ttl => 86400, }, 'get_user' => { :updaters => ['add_user', 'mod_user', 'delete_user'], :ttl => 86400, }, 'get_all_users' => { :updaters => ['add_user', 'delete_user'], :ttl => 86400, }, 'get_oa_info' => { :updaters => [], :ttl => 86400 * 3, }, } @cachable.each do |k, v| v[:updaters].push('factory_defaults') end end def call(method, *args) @cachable.each do |reader,opts| if(opts[:updaters].include?(method)) cachefile = File.join(@cachedir, reader) if File.exists?(cachefile) File.unlink(cachefile) end Dir.glob(cachefile + '_*') do |filename| File.unlink(filename) end end end args = args.clone args.insert(0, '--json', @hostname, method) args.insert(0, '-Plocal') if @local @provider.hpilo_cli(*args) end def get(method, *args) args = args.clone args.insert(0, '--json', @hostname, method) if(@cachable.include?(method)) cachefile = File.join(@cachedir, method) if(args.length > 3) cachefile += '_' + args.slice(3,args.length).join() end cutoff = Time.new - @cachable[method][:ttl] if(File.exist?(cachefile) && File.mtime(cachefile) > cutoff) args.insert(0, '--read-response', cachefile) else if File.exist?(cachefile) File.unlink(cachefile) end args.insert(0, '--save-response', cachefile) end end args.insert(0, '-Plocal') if @local json = @provider.hpilo_cli(*args) JSON.parse(json) end def check_password(login, password) begin @provider.hpilo_cli('-l', login, '-p', password, @hostname, 'get_fw_version') true rescue false end end def fw_config() cachefile = File.join(File.dirname(Puppet[:confdir]), 'firmware.conf.json') cutoff = Time.new - 86400 if(!File.exist?(cachefile) || File.mtime(cachefile) < cutoff) json = @provider.python("-c", "import hpilo_fw, json; print(json.dumps(hpilo_fw.config()))") f = File.new(cachefile, 'w') f.write(json) f.close() end f = File.new(cachefile) json = f.read() f.close() JSON.parse(json) end end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/network_device/ilo/facts.rb0000644000175000017500000000107112652734620032452 0ustar dennisdennis00000000000000require 'puppet/util/network_device/ilo' class Puppet::Util::NetworkDevice::Ilo::Facts attr_reader :transport def initialize(transport) @transport = transport end def retrieve facts = { 'devicetype' => 'ilo', 'users' => @transport.get('get_all_users'), } facts.merge! @transport.get('get_fw_version') begin facts.merge! Hash[@transport.get('get_oa_info').map{ |k,v| [ 'oa_'+ k, v ] }] rescue end Hash[facts.map{ |k,v| [ k.to_sym, v ] }] end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/network_device/ilo/device.rb0000644000175000017500000000156212652734620032616 0ustar dennisdennis00000000000000require 'puppet/util/network_device/ilo/facts' require 'puppet/util/network_device/ilo/transport' require 'uri' class Puppet::Util::NetworkDevice::Ilo::Device attr_accessor :hostname, :transport, :local def initialize(uri, option = {}) uri = URI.parse(uri) @hostname = uri.host @local = uri.scheme == 'ilo' @option = option Puppet.debug("(iLO device) connecting to iLO #{@hostname} #{@option.inspect}.") @transport = Puppet::Util::NetworkDevice::Ilo::Transport.new(@hostname, @local) Puppet.debug("Transport created") end def facts @facts = Puppet::Util::NetworkDevice::Ilo::Facts.new(@transport) facts = @facts.retrieve Puppet.debug("(iLO device) Facts retrieved: #{facts.inspect}") facts.each do |k,v| Facter.add(k) do setcode do v end end end facts end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/util/network_device/ilo.rb0000644000175000017500000000012212652734620031346 0ustar dennisdennis00000000000000require 'puppet/util/network_device' module Puppet::Util::NetworkDevice::Ilo end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/type/0000755000175000017500000000000012652734620025237 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/type/ilo_settings.rb0000644000175000017500000000122512652734620030267 0ustar dennisdennis00000000000000Puppet::Type.newtype(:ilo_settings) do desc "Manage iLO settings" apply_to_device newparam(:name, :namevar=>true) do desc "Which settings" end newproperty(:settings) do desc "The settings" def retrieve provider.settings end def insync?(is) @should.each do |should| is.keys.each do |key| should.include?(key) || is.delete(key) end should.keys.each do |key| return false if should[key].to_s != is[key].to_s end end true end end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/type/ilo_license.rb0000644000175000017500000000035012652734620030047 0ustar dennisdennis00000000000000Puppet::Type.newtype(:ilo_license) do desc "Manage iLO licenses" apply_to_device newparam(:name, :namevar=>true) do desc "License name" end newproperty(:key) do desc "License key" end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/type/ilo_user.rb0000644000175000017500000000444312652734620027412 0ustar dennisdennis00000000000000Puppet::Type.newtype(:ilo_user) do desc "Manage iLO users" apply_to_device ensurable newparam(:name, :namevar=>true) do desc "User loginname" end def munge_boolean(value) case value when true, "true", :true true when false, "false", :false false else fail("munge_boolean only takes booleans") end end newproperty(:password) do desc "Password" def insync?(is) if(is == :absent) return provider.verify_password(@should[0]) end is == @should[0] end end newparam(:password_atcreate) do desc "Password, only used when creating users" end newproperty(:display_name) do desc "User's display name" end newproperty(:admin_priv, :boolean => true) do desc "Admin privileges" newvalues(:true, :false) munge do |value| @resource.munge_boolean(value) end end newproperty(:config_ilo_priv, :boolean => true) do desc "iLO configuration privileges" newvalues(:true, :false) munge do |value| @resource.munge_boolean(value) end end newproperty(:remote_cons_priv, :boolean => true) do desc "Remote console privileges" newvalues(:true, :false) munge do |value| @resource.munge_boolean(value) end end newproperty(:reset_server_priv, :boolean => true) do desc "Server reset privileges" newvalues(:true, :false) munge do |value| @resource.munge_boolean(value) end end newproperty(:virtual_media_priv, :boolean => true) do desc "Virtual Media privileges" newvalues(:true, :false) munge do |value| @resource.munge_boolean(value) end end validate do if @parameters[:ensure].value != :absent && !Facter.value(:users).include?(@parameters[:name].value) unless @parameters.include?(:display_name) raise Puppet::Error, "A display_name is mandatory for #{@parameters[:name].value}" end unless (@parameters.include?(:password) or @parameters.include?(:password_atcreate)) raise Puppet::Error, "A password is mandatory for #{@parameters[:name].value}" end end end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/type/ilo_firmware.rb0000644000175000017500000000302412652734620030242 0ustar dennisdennis00000000000000Puppet::Type.newtype(:ilo_firmware) do desc "Manage iLO firmware" apply_to_device ensurable do attr_accessor :latest newvalue(:latest) do begin provider.install rescue => detail self.fail "Could not update: #{detail}" end end newvalue(/./) do begin provider.install rescue => detail self.fail "Could not update: #{detail}" end end def insync?(is) @should.each do |should| case when is == should return true when should == :latest && is == provider.fw_config[@resource.name.downcase]['version'] return true end end false end def retrieve provider.firmware_version end defaultto :latest end newparam(:name, :namevar=>true) do desc "Ilo type" validate do |value| unless value =~ /ilo[234]?/i fail Puppet::Error, "Unknown iLO type, '#{value}'" end if value.downcase != Facter.value(:management_processor).downcase fail Puppet::Error, "This server has an #{Facter.value(:management_processor)}, not an #{value}" end end end newparam(:http_proxy) do desc "HTTP proxy for downloading firmware" defaultto "" end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/0000755000175000017500000000000012652734620026110 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_user/0000755000175000017500000000000012652734620027731 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_user/ilo_user.rb0000644000175000017500000000341312652734620032100 0ustar dennisdennis00000000000000require 'puppet/provider/ilo' Puppet::Type.type(:ilo_user).provide(:ilo_user, :parent => Puppet::Provider::Ilo) do @doc = "Manages iLO users" mk_resource_methods def self.lookup(device, id) begin user = device.transport.get('get_user', "user_login=#{id}") rescue return nil end { :name => user['user_login'], :password => :absent, :display_name => user['user_name'], :admin_priv => user['admin_priv'], :config_ilo_priv => user['config_ilo_priv'], :remote_cons_priv => user['remote_cons_priv'], :reset_server_priv => user['reset_server_priv'], :virtual_media_priv => user['virtual_media_priv'], } end def verify_password(password) device.transport.check_password(name, password) end def propmap(props, oldprops=nil) props = props.map do |k,v| next if [:name, :ensure].include?(k) next if oldprops and props[k] == oldprops[k] if k == :display_name "user_name=#{v}" else "#{k}=#{v}" end end props.insert(0,"user_login=#{name}") props.reject do |p| p == nil end end def flush if properties[:ensure] == :absent device.transport.call('delete_user', "user_login=#{name}") elsif former_properties[:ensure] == :absent: cproperties = properties cproperties[:password] ||= resource[:password_atcreate] device.transport.call('add_user', *propmap(cproperties)) else device.transport.call('mod_user', *propmap(properties, former_properties)) end end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_settings/0000755000175000017500000000000012652734620030613 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_settings/ilo_settings.rb0000644000175000017500000000215112652734620033642 0ustar dennisdennis00000000000000require 'puppet/provider/ilo' Puppet::Type.type(:ilo_settings).provide(:ilo_settings, :parent => Puppet::Provider::Ilo) do @doc = "Manages iLO settings" attr_reader :supported @supported = { 'network' => { :reader => 'get_network_settings', :writer => 'mod_network_settings', }, 'global' => { :reader => 'get_global_settings', :writer => 'mod_global_settings', }, 'dir' => { :reader => 'get_dir_config', :writer => 'mod_dir_config', }, 'snmp' => { :reader => 'get_snmp_im_settings', :writer => 'mod_snmp_im_settings', }, } mk_resource_methods def self.lookup(device, id) fail Puppet::Error, "Unknown settings type #{id}" unless @supported.include?(id); settings = device.transport.get(@supported[id][:reader]) {:name => id, :writer => @supported[id][:writer], :settings => settings} end def flush device.transport.call(properties[:writer], *properties[:settings].map{|k,v| "#{k}=#{v}"}) end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_license/0000755000175000017500000000000012652734620030375 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_license/ilo_license.rb0000644000175000017500000000122412652734620033206 0ustar dennisdennis00000000000000require 'puppet/provider/ilo' Puppet::Type.type(:ilo_license).provide(:ilo_license, :parent => Puppet::Provider::Ilo) do @doc = "Manages iLO settings" mk_resource_methods def self.lookup(device, id) instance = nil device.transport.get('get_all_licenses').each do |license| if license['license_type'] == id instance = { :name => license['license_type'], :key => license['license_key'], } end end instance end def flush device.transport.call('activate_license', "key=#{properties[:key]}") end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_firmware/0000755000175000017500000000000012652734620030567 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo_firmware/ilo_firmware.rb0000644000175000017500000000256412652734620033602 0ustar dennisdennis00000000000000require 'puppet/provider/ilo' Puppet::Type.type(:ilo_firmware).provide(:ilo_firmware, :parent => Puppet::Provider::Ilo) do @doc = "Manages iLO firmware" def firmware_version() @property_hash[:firmware_version] end def self.lookup(device, id) version = device.transport.get('get_fw_version') { :name => version['management_processor'], :management_processor => version['management_processor'], :firmware_version => version['firmware_version'], :firmware_date => version['firmware_date'] } end def fw_config old_https_proxy = ENV['https_proxy'] old_http_proxy = ENV['http_proxy'] begin ENV['http_proxy'] = ENV['https_proxy'] = resource[:http_proxy] device.transport.fw_config ensure ENV['https_proxy'] = old_https_proxy ENV['http_proxy'] = old_http_proxy end end def install Puppet::debug("Installing firmware version #{@resource[:ensure]}") old_https_proxy = ENV['https_proxy'] old_http_proxy = ENV['http_proxy'] begin device.transport.call('update_rib_firmware', "version=#{@resource[:ensure]}") ensure ENV['https_proxy'] = old_https_proxy ENV['http_proxy'] = old_http_proxy end end end python-hpilo-3.6/examples/puppet/modules/ilo/lib/puppet/provider/ilo.rb0000644000175000017500000000073712652734620027227 0ustar dennisdennis00000000000000require 'puppet/util/network_device/ilo/device' require 'puppet/provider/network_device' class Puppet::Provider::Ilo < Puppet::Provider::NetworkDevice attr_writer :device def self.device(url) @device = Puppet::Util::NetworkDevice::Ilo::Device.new(url) @device end def self.mkcommands @commands ||= {} commands :python => "python", :hpilo_cli => "hpilo_cli"; end def mkcommands self.class.mkcommands end end python-hpilo-3.6/examples/elasticsearch/0000755000175000017500000000000012652734620021235 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/elasticsearch/servers.py.example0000644000175000017500000000126312652734620024734 0ustar dennisdennis00000000000000# Since the elasticsearch importer needs to know about all your servers, let's # extract that method so you can easily use the elasitcsearch importer. From # this function you should query your infrastructure database or do whatever # you do to get a list of all servers. The function should return a list of # ilo names or ip addresses # # This example implementation merely returns a static list of hosts. def get_all_ilos(): return [ 'example-server-1.int.kaarsemaker.net', 'example-server-2.int.kaarsemaker.net', 'example-server-2.int.kaarsemaker.net', '10.42.128.1', '10.42.128.2', '10.42.128.3', '10.42.128.4', ] python-hpilo-3.6/examples/elasticsearch/kibana-dashboard.json0000644000175000017500000001016412652734620025304 0ustar dennisdennis00000000000000[ { "_id": "iLO-Dashboard", "_type": "dashboard", "_source": { "title": "iLO Dashboard", "hits": 0, "description": "", "panelsJSON": "[{\"col\":1,\"id\":\"iLO-types\",\"row\":1,\"size_x\":4,\"size_y\":3,\"type\":\"visualization\"},{\"col\":5,\"id\":\"iLO-firmware-versions\",\"row\":1,\"size_x\":8,\"size_y\":3,\"type\":\"visualization\"},{\"col\":1,\"id\":\"Remote-syslog-enabled\",\"row\":4,\"size_x\":3,\"size_y\":2,\"type\":\"visualization\"},{\"id\":\"Telnet-enabled\",\"type\":\"visualization\",\"size_x\":3,\"size_y\":2,\"col\":4,\"row\":4}]", "version": 1, "timeRestore": false, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"filter\":[{\"query\":{\"query_string\":{\"analyze_wildcard\":true,\"query\":\"*\"}}}]}" } } }, { "_id": "iLO-types", "_type": "visualization", "_source": { "title": "iLO types", "visState": "{\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":false,\"addLegend\":false,\"scale\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"fw_version.management_processor\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", "description": "", "version": 1, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"index\":\"hpilo\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" } } }, { "_id": "iLO-firmware-versions", "_type": "visualization", "_source": { "title": "iLO firmware versions", "visState": "{\"type\":\"histogram\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"scale\":\"linear\",\"mode\":\"grouped\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"fw_version.management_processor\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"1\"}},{\"id\":\"3\",\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"fw_version.firmware_version\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", "description": "", "version": 1, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"index\":\"hpilo\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" } } }, { "_id": "Remote-syslog-enabled", "_type": "visualization", "_source": { "title": "Remote syslog enabled", "visState": "{\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"global_settings.remote_syslog_enable\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", "description": "", "version": 1, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"index\":\"hpilo\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" } } }, { "_id": "Telnet-enabled", "_type": "visualization", "_source": { "title": "Telnet enabled", "visState": "{\"type\":\"pie\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"isDonut\":false},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"global_settings.telnet_enable\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}],\"listeners\":{}}", "description": "", "version": 1, "kibanaSavedObjectMeta": { "searchSourceJSON": "{\"index\":\"hpilo\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}" } } } ] python-hpilo-3.6/examples/elasticsearch/hpilo_es_import0000755000175000017500000001274112652734620024364 0ustar dennisdennis00000000000000#!/usr/bin/python # # (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details try: import ConfigParser except ImportError: import configparser as ConfigParser import hpilo import optparse import datetime import elasticsearch import multiprocessing import re import os import sys import servers # If this import fails, look at servers.py.example def main(): usage = """%prog [options]""" p = optparse.OptionParser(usage=usage) p.add_option("-l", "--login", dest="login", default=None, help="Username to access the iLO") p.add_option("-p", "--password", dest="password", default=None, help="Password to access the iLO") p.add_option("-c", "--config", dest="config", default="~/.ilo.conf", help="File containing authentication and config details", metavar="FILE") p.add_option("-t", "--timeout", dest="timeout", type="int", default=60, help="Timeout for iLO connections") p.add_option("-P", "--protocol", dest="protocol", choices=("http","raw"), default=None, help="Use the specified protocol instead of autodetecting") p.add_option("-d", "--debug", dest="debug", action="count", default=0, help="Output debug information, repeat to see all XML data") p.add_option("-o", "--port", dest="port", type="int", default=443, help="SSL port to connect to") p.add_option("-x", "--processes", dest="processes", type="int", default=50, help="How many servers to scan in parallel") opts, args = p.parse_args() if args: p.print_help() p.exit(1) if not os.path.exists(os.path.expanduser(opts.config)): p.error("Configuration file does not exist") config = ConfigParser.ConfigParser() config.read(os.path.expanduser(opts.config)) # Do we have login information login = None password = None if config.has_option('ilo', 'login'): login = config.get('ilo', 'login') if config.has_option('ilo', 'password'): password = config.get('ilo', 'password') if opts.login: login = opts.login if opts.password: password = opts.password if not login or not password: p.error("No login details provided") # Connect to ES and create our index es_host = None if config.has_option('elasticsearch', 'host'): es_host = config.get('elasticsearch', 'host') es = elasticsearch.Elasticsearch(es_host) if not es.indices.exists('hpilo'): print "Creating hpilo index" es.indices.create(index='hpilo') mapping = { "_timestamp": { "enabled": True, "path": "last_updated" }, "properties": { "status": { "type": "string", "index": "not_analyzed" }, } } add_string_property(mapping, "network_settings.nic_speed") add_string_property(mapping, "host_data.fields.value") add_string_property(mapping, "xmldata.bladesystem.manager.rack") es.indices.put_mapping(index='hpilo', doc_type='hpilo', body={'hpilo': mapping}) # Scan all servers and import data ilos = servers.get_all_ilos() ilos = [(ilo, login, password, opts.timeout, opts.port, opts.protocol, opts.debug, es_host) for ilo in ilos] if opts.processes == 1: for ilo in ilos: scan_ilo(ilo) else: multiprocessing.Pool(opts.processes).map(scan_ilo, ilos) # Finally, clean up stale data (older than 7 days) limit = (datetime.datetime.now() - datetime.timedelta(7)).strftime('%Y-%m-%dT%H:%M:%s') query = { "constant_score": { "filter": { "range": { "last_updated": { "lte": limit } } } } } es.delete_by_query(index='hpilo', doc_type='hpilo', body={'query': query}) def scan_ilo(args): name, login, password, timeout, port, protocol, debug, es_host = args print("Scanning %s" % name) ilo = hpilo.Ilo(name, login, password, timeout, port, delayed=True) ilo.debug = debug if protocol == 'http': ilo.protocol = hpilo.ILO_HTTP elif protocol == 'raw': ilo.protocol = hpilo.ILO_RAW data = {'status': 'ok'} try: ilo.get_fw_version() ilo.get_host_data() ilo.get_global_settings() ilo.get_network_settings() ilo.get_all_user_info() data['fw_version'], data['host_data'], data['global_settings'], \ data['network_settings'], data['all_user_info'] = ilo.call_delayed() ilo.delayed = False try: data['oa_info'] = ilo.get_oa_info() except hpilo.IloError: data['oa_info'] = None data['xmldata'] = ilo.xmldata() except hpilo.IloError: e = sys.exc_info()[1] data['status'] = 'error' data['error'] = str(e) now = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S') es = elasticsearch.Elasticsearch(es_host) try: stored = es.get(index='hpilo', doc_type='hpilo', id=name) es.update(index='hpilo', doc_type='hpilo', id=name, body={'doc': data}, timestamp=now) except elasticsearch.exceptions.NotFoundError: es.index(index='hpilo', doc_type='hpilo', id=name, body=data, timestamp=now) def add_string_property(mapping, key): rest = key.split('.', 1) mine = rest.pop(0) if rest: mapping["properties"][mine] = {"properties": {}} add_string_property(mapping["properties"][mine], rest[0]) else: mapping["properties"][mine] = {"type": "string"} if __name__ == '__main__': main() python-hpilo-3.6/examples/elasticsearch/hpilo_es_dump0000755000175000017500000000230112652734620024006 0ustar dennisdennis00000000000000#!/usr/bin/python # # (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details try: import ConfigParser except ImportError: import configparser as ConfigParser import optparse import elasticsearch from pprint import pprint import os def main(): usage = """%prog [options]""" p = optparse.OptionParser(usage=usage) p.add_option("-c", "--config", dest="config", default="~/.ilo.conf", help="File containing authentication and config details", metavar="FILE") opts, args = p.parse_args() if args: p.print_help() p.exit(1) es = None if os.path.exists(os.path.expanduser(opts.config)): config = ConfigParser.ConfigParser() config.read(os.path.expanduser(opts.config)) if config.has_option('elasticsearch', 'host'): es = elasticsearch.Elasticsearch(config.get('elasticsearch', 'host')) if not es: es = elasticsearch.Elasticsearch() request = {'query': {'match_all': {}}, 'size': 20000} ilos = es.search(index='hpilo', doc_type='hpilo', body=request) for ilo in ilos['hits']['hits']: pprint(ilo['_source']) if __name__ == '__main__': main() python-hpilo-3.6/examples/firmwareupdater/0000755000175000017500000000000012652734620021624 5ustar dennisdennis00000000000000python-hpilo-3.6/examples/firmwareupdater/hpilo_firmware_update0000755000175000017500000000772712652734620026140 0ustar dennisdennis00000000000000#!/usr/bin/python # # (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details try: import ConfigParser except ImportError: import configparser as ConfigParser import hpilo import hpilo_fw import optparse import datetime import elasticsearch import re import os import sys import syslog import azuki def main(): usage = """%prog [options]""" p = optparse.OptionParser(usage=usage) p.add_option("-c", "--config", dest="config", default="~/.ilo.conf", help="File containing authentication and config details", metavar="FILE") p.add_option("-t", "--timeout", dest="timeout", type="int", default=60, help="Timeout for iLO connections") opts, args = p.parse_args() if args: p.print_help() p.exit(1) if not os.path.exists(os.path.expanduser(opts.config)): p.error("Configuration file does not exist") config = ConfigParser.ConfigParser() config.read(os.path.expanduser(opts.config)) # Do we have login information if not config.has_option('ilo', 'login') or not config.has_option('ilo', 'password'): p.error("No login details provided") # Connect to ES if config.has_option('elasticsearch', 'host'): es = elasticsearch.Elasticsearch(config.get('elasticsearch', 'host')) else: es = elasticsearch.Elasticsearch() if config.has_option('beanstalkd', 'host'): bs = config.get('beanstalkd', 'host').split(':') azuki.add_beanstalk(bs[0], int(bs[1])) # Fetch all obsolete ilos config = hpilo_fw.config() request = {'query': {'bool': {'should': [ {'query_string': {'query':'fw_version.management_processor:\'ilo2\' AND NOT fw_version.firmware_version:%s' % config['ilo2']['version']}}, {'query_string': {'query':'fw_version.management_processor:\'ilo3\' AND NOT fw_version.firmware_version:%s' % config['ilo3']['version']}}, {'query_string': {'query':'fw_version.management_processor:\'ilo4\' AND NOT fw_version.firmware_version:%s' % config['ilo4']['version']}}, ]}}, 'size': 50000} ilos = es.search(index='hpilo', doc_type='hpilo', body=request) for ilo in ilos['hits']['hits']: upgrade_firmware(opts.config, config, ilo['_source']) def log(message): print message syslog.syslog(message) def print_progress(message): sys.stdout.write('\r\033[K' + message) sys.stdout.flush() @azuki.beanstalk('hpilo-upgrades', ttr=1200) def upgrade_firmware(ilo_config, firmware_config, ilo): config = ConfigParser.ConfigParser() config.read(os.path.expanduser(ilo_config)) if not config.has_option('ilo', 'login') or not config.has_option('ilo', 'password'): p.error("No login details provided") login = config.get('ilo', 'login') password = config.get('ilo', 'password') name = '%s.%s' % (ilo['network_settings']['dns_name'], ilo['network_settings']['domain_name']) ip = ilo['network_settings']['ip_address'] port = ilo['global_settings']['https_port'] ilo_type = ilo['fw_version']['management_processor'].lower() from_version = ilo['fw_version']['firmware_version'] to_version = firmware_config[ilo_type]['version'] log("Upgrading %s (%s) from %s %s to %s %s" % (name, ip, ilo_type, from_version, ilo_type, to_version)) ilo = hpilo.Ilo(ip, login, password, port=port) version = ilo.get_fw_version() if version['firmware_version'] >= to_version: return # iLO3 may need to be upgraded in two steps because older firmware versions were very buggy if version['management_processor'].lower() == 'ilo3' and version['firmware_version'] < '1.28': log("Upgrading %s (%s) from %s %s to %s 1.28 as intermediate step" % (name, ip, ilo_type, from_version, ilo_type)) ilo.update_rib_firmware(version='1.28') print("") raise azuki.Reschedule(delay=120) ilo.update_rib_firmware(version=to_version, progress=print_progress) print("") if __name__ == '__main__': main() python-hpilo-3.6/docs/0000755000175000017500000000000012652734620015535 5ustar dennisdennis00000000000000python-hpilo-3.6/docs/_static/0000755000175000017500000000000012652734620017163 5ustar dennisdennis00000000000000python-hpilo-3.6/docs/_static/python-hpilo.png0000644000175000017500000002677312652734620022342 0ustar dennisdennis00000000000000‰PNG  IHDRwz…§ÌTbKGD7r£òè‘… pHYs  šœtIMEÞ; Ú›‚ IDATxÚí½y|e÷ÿ¾÷³''[Ó&mé^J+ÐPVñ6~ˆÂ ¢Èã3Ã82 Î8Œ,ó Î *¨ »P:‚V HY¤--tIÛ4M›f=INÎ~o×ï;÷ݤMš¤MKur½^yœœsßç:×ç»~¾ßë LŒ‰11&ÆÄ˜cbLŒ‰11†ÒŸóäWnh»©¡-s¶´fÈLÚzóìî-€Þ-@ô?“ËÃÔ–G‚çKfT‚ÉÉhúü¥ÓË'À=Œã±7šÄê¦n¶´ehíÍÊÃNôC(=ü»áù`!ˆ‡5fO.cÉŒj¾|Î1Ò¸ã8nf½XÓÔCkOax`övÐÇ ìàçÞïs§”sùGç¤Ï?aFù¸8nøÙ;buS÷ …;°bäëÇìÀ÷ONFxöï.&Àøgù&ñø›ÍcæÐ» pí'òåO.’&ÀaÜñÌûbÙÚÝ£^ØñV x%°{½vÞÒÜvÅIG$Àò‘0‰‡þ°mœ{~°Þ½—½ÓÈí­àî+ÛÆ¬ØÑjð~®b`÷Ü{Ù;<öêÆ#`õÈ0Ç-Ã.Þäò—Ÿ|s''ˆ*­½[µÕ©Ñ»÷k#ùÜ´îyöÝ Ÿ»÷¸øžWÅ TgÀâÍ©óÀ5' iû\·lõNîxú½‘ƒ¡‘€Ç@ë¼fqÛgO9büï‡n–‡6R‡à¼ÅS¹ö¬9C˜ÒñVP½ìí­>wðÚÜw|ݰÀúãòSfŽÍŸŠÁÁиZž?¶rƒ˜X¹±ý¦¡£\8m~͈×ÇCs'— ³Ð‡(ÐAãWok›¨¶´eîÛë4š5ÔqaFì× ÈäÍ ³<ØÐÚ7ª[¬ÙÞ5ŽÀŠƒÙ¸ûúÜy¥@°lõ®¯\¶ºù¢ÜQБb¤Ôjø¸¡%5îм‡uÚÒ–æže {ICkš{^XðQ®!‚Þ[0Fm&HŒýÒ‰¯j¤µ'ÏÍçÃäd€LÑâÕ ­ÜóÂz²EkœéÄјíý{$ÑT2¸#óįnlåÕ­ÄB*“Ë#liM8xÐþx$`,òÃ×\IFˆR³‹-…ôa£ÇQiÀàŽØ‹N< `…˜wTÀŽ´°c¢9´ÀŠ Í"˜:@`#ë4œý6.µ°°û벜H…Ž$`Ç% ÒÑ|Öÿpp¿üñy‡­öù×?úX½µcÌtâ¾9쟰GŽY>¼ÑCÒ‰£"'ÆèM€û!¡<ÆxLÀþ¥ù\oÏNß}­=Z{òCòOÛÂ|Þþ€Ò”µ ¶ìî9:ñ@âþ¿öþL`6 ~}¨yú÷2‚Vó#)þñ—öy/¬ÞÕûêÆö²W7u0ö¶Óq†78†ëß¾ÿº`]EÇw¥÷÷v¯{ ÷;iÒÍŒÑU….¾{¥ø§gÖì´ ÆV[W:q|Ý×âˆ}£VȬ@4^.Dúwrpïxf½8é¶åbé رЉbt¬Ó‡ÉE0„Û!æ"ÀÉAÇ=_]¿‡ ÜÏ?ðG±lÍ®ý.Þ¨èÄðbŒMtâhîÀ÷wÿ‘~ù×ãP}þ?Š-m}£v4•™CÇóR:QŒÁ:ì/«æ¼®íîËÆUsoøéÛ€ÝW+ÄPÀŠƒå‰#°bœ‡Hs}lþ¿b\À}lU“X½=uv±ª€žX`Öxùܽ¯Ë­Cô¾ôÂA›å‡VlÝ×Ü|›Çåúq!'FŒ7À{Í©ûÙó*ÏÅÂ4MLÓ$S^^NWW–eá8‘H×u) hš†eYÞ ¥Á·”$ I’Pd Ó2Ñ5×u±EVp\Y’‘e Û±€iS§ÑÖÖ†i•øèÉ'rçwòÄOÐÜÜÌñÇišÔÕÕÑÞÞδú)ضMGGùR‘R©€#\R©¥R +o"„@Ó4lÛÆ4Mt]'£ë:ù¢I(¢§§Ó4QU•ÆÆF¦OŸÎw¾ó^}}%·ß~;–åÇùÜç>ÇÃ?L¡PB’$d„!!„,‚"‡„$I¨š„iš¸®‹®ë˜¦‰$I!PUÛvƒõ8¡0…b!X}~ƘÁ½øâKE6›%“ÉH$ÈçóTVV2uêTxÿý÷‰F£(ŠB>Ÿïÿ@×uƒßýÑÞÖÉ¥—^Êœ9sX³f /¿ü2K–,aÉ’%”—U³iÓ&þðÊﱬW]uÛxõµW<Á^xû·ËÔ©Sijj¢³³“T*…$I¨„‰D”J´°B2™ ²¦E‘H$âHnL&ƒã@>W =Š‘p”|É¿¾¾Ã0(•JÄãqºººxçwøÚ×o$‹±³¹…¿þë¯rÔQGño|“²DÓ4QT)Xƒ\.¬k4R. …º®á8†a¯ª*ù|žH$‚ã8 Âá°j8L±XÜã?ïÞ¶mcY²,“Ïg¥1›å¿»õ6‡Éçóäóyb±²,3}útzzzØÒ°²D!fɤ²¢š|>êI²<@Êí]D"yäŽ9æfÍš…ëº$“IV®\‰®E™6½E‘èMg™1s¶SÀy¥„‚xDcù²çyþ¹ç‘eP°,PU°m/|Ð Ë)õË8ÄË5ÊËTTT0yR YR©¨¨DQ4*íí¬_÷¶í2eJ=¶m£i‰D‚x<ÎîÝ»Y¿þ}lŽš=³Ï>›U«V¡(ÙlYRI&“”J&»_[r¹L°–Ñhãi ’$aY®ëR]]eYFÇq¨ªª¢··—h4J>Ÿ'â8Ùl–P(DÈ#I¡PUU)‹ìhÎŽÝç~ÿûß'‰H$p‡L&ƒëºÁ¤‰¡PˆH$B&“!‹aÛ6®ë-­¢(8Žƒã8H’ÌgœÉé§ŸAYY»wïF§v:sçÎ%“É¡ª2--ͤº;…TŽ+dȬ@‚% ,»ßîôÿH’‹å–Pp³VIEW+±J;·0 ƒ¶-ìÜÕ„+L„pH§mdºRdÙ»¿,{ÂŽÀ¶mÍ47?„e¡‡ùÆ7þUUUôõe¨¨¨Bï»Ëò൪ª†êêjêëë±,‹Ý»wÓÞÞN¡P¤««‹ãŽ;ŽîînR©NŽ>úhz{{1ŒÉd]78õÔÓÈçóìÜÙL[[¶mSUUE(:°€jÞ¼y˜š¦QSSÓoò8޼V, …B躎,ËȲŒëºƒü®ëºØ¶Muu5¯½ö , •JÑÛÛ Àúõë±, I’èêêdWK3†¡¡é º®pÑÅŸäK_úù¾^dYFQŠÅ"ªª"Ë2étšP(„{‘ЈE“|°¡‰ÿ÷ïÒÚ–&Ýc¡©*Q¥×T(–Ò˜3Î:•sÎ=ÓÊ é2¹œƒ¢(¨ªJ¡P@Q¢Ñ(–eaš&Z(ÎêÕkY±âtuuQ^^NEEù|!ðå¾8’É$ , N“H$‡Ã”••±zõjJ¥çž{.===Ü{ßÝœ~úélÞ¼™xŸã³W~ž{ﻇ’é Eù_gž…n›7{9«„^E¦T01\ 9oBÁd·š¥¼¬’úishlø/ÚÛRÈ’B_®“P4B‘^br)d‘uRœuÎ)\xÁ¹ìln$—Ë¢ÛF4B$CÖUlË¡¯7Mu²‰T®ƒù3êøÕ/Eí”zÚSݘýfa㸡p,,ý±xÉêëëÙ¹£›)uµ¬]»š£>Mñì³O!«Ð¼« U5Èå‹¡í]LŸ%ŽòÁ†MÜÿñqóF®¾új~ûòKÔÔÔ ë:¥Rilšûö«¿¿Ä7-¾6ʲL*•bÚ´iìÞ½Y–õýƒÑÖÖFee%½½½$“IÒé4š¦FijjbòäÉ<ýôÓD£Q®¹æ¶nÝÊŠ+ˆ…ᩯ4'I‘H„p8Ì–-[xø¹' [=& ÓÛÖΤx9Ÿ<íL–ÊÖ®íØ®FOwÚ#W„gEâñ8²¢R*À±qظa ›4ÒÕÑJY"FÑ*²}}¯®ú#‰d9áXU’)ŠtvtpþÙg0wÞ1TT”‘Íf-Ïgs„ EQ<`%iPN‡q]—]-Ít¥:¼¬#ÕÉ;ï¼C(lÇ‘$ Û¶¨¯¯§££ƒdÒ‹g:::øÄ'>¢(lÞ¼™X,†ã8„B!,ËBUÕ±ëëGt¾iM$tuu¡iôõõ‘ËåˆD"ȲLOOA”ËåˆÇã”J%4M£¹¹™ÆÆF¢Ñ(íííìhjâÜsÏeÓ¦M^ÄëºH²LyE}}}¼úê«,œûE*++ùÕsÏ!Å „"0eQ:[ZøØ’¥|¼âœ¸þ†¯ÒÑUD’dY#O «2ŽiQ°mEfRM-ÁC?ý9>øs ùÙ©;ªŽ·×¯æ×O-¤(TU•aš&é®KŽ™Çœ¹ ‚ïê8N°6Š¢xѲ$±iãºÀé–•W ǵH”Å8úèy‹ytCcåÊwiiiFV$¶oßÎùçŸÏ²e/RU]ãZžYŽ…‰ÆÂÞß“Ûo¿––"‘BŠÅ"ýk5jp}@ëº.±H×u ‡Ã¤Ói„455á8²,3irmXÅb1Âá0Ô×דÉd˜2e MMM˜¦I[[ -â ««‹\6‹„`êÔiض¢ë‹E/^Œiš„C_ý—Èò8*8X 9¤&µ±tÑG™6ÉÊ:B‘8²\YCB&“ÉPV–ðü§Å6‹ìniGSê¦Ì XÊÒÙÞI(–D²Skë9眓ÑQ]AëX–E1ŸcÞ¼y躎¦ihšŠ¦iAÎêÇš6ø$€R©Ä}÷ÝÇ•W^ÉäÚéhºÌk¯­äÍ7ÿÈœ9séîéâ™gžaÁ‚<ûì³lÚ´‰'Ÿ|’Ë/¿œÊÊJ¶lÙB<ç…eËX·î=yäb±’$a®ë2sÖ<Ѹm³4*pDýÜʶmvíÚ…ã8ÜxãÌœ9Û¶yãÍU¬X±‚t:M:¦®®Žššúú¼}¶Û·oçÜsÏeÛ¶m|þóŸçñÇgGS_¹î:.»ì2¶nÞÌWo¼‘ªšÓÄ0 tÅÓáZü¯NÃ6ÓgE4!YQFoo7ª"“êè$”('YUKk{Ç‘ˆD=ÿ …plU‰’H$Èå$TEB–%ÂJ-”!KR óÑÅ'qúÇNCOD@|!K©T /Ý‹”·ú£~/?Åb^F  EÁ.ë×½;h‘gΜAoo/=ö+„+cY&áHˆY³g ëTÊ•¤R]\wÝu̘1ƒÖÖVêꦰ|ù‹D"Eá3Ÿ¹,\Ãáp`²#‘H‹Js¿xýÍO½µòwƒLóÀÐ^ÁÖ­[©©©aãÆlܸ‘¯}íkȲÌÉ=…{ï½—_þò—¼ûî»ôöö‡Ñ4-H‡’É$ÕÕÕ|êSŸâ{wÞÉÍßü&_øÂ¸æšk¸îÚkY¾|97ÞtmžÆê^DlY&;[šQ…ž¾4 TVUyQ,)›”¢X²’L$%ÓÛÛhª†,9”ŠyTEBÕ5Šý¬¬h¼ðâ2N8j½™>"åqR½˜ŽImM%õ“kɦ{q‰Iµõ¨ªŠeYÄb1í2ûGu°ÖžøW…BŠŠ êêêå°^žê1{S§N¥²² DZ©©©!‰DPU•R©Ä”)S0M“iÓ¦ÑÚÚSº®©çˆàþéõ?Á”Ï4ùdD©TÂ0 2Ù }}Ýüä'?çÚ/_K$¡P(ðÊÊW8ÿ‚ øú׿Î~ð6mÚ„®ëôôôP[[øíx¨s©2\ý¹Ë¸ì¢‹0äJD"’É$»vwz™A¿ËB°níŸim*åmÂö5LV\$ÙÁq,B!ËòÖØIB!Y–) ˜¦‰í13¨ªŠã87àó ¥’G{ …ÑU…4M òG!D q®ëbkß[Ë¿üó¿`š.ÿðÿ€¦jä y$I¢®¾žžžŽŽ®¹æ2™ ­­­ÔÖÖ’J¥Èd2ÌŸ?? 74]góæÍœzê©(ªŠe[L:•ÆÆFô°ÇÆìÞ½;ˆóꮉD(í~ÞÖaPÊ; @5Â8Ž‹ªiÈ’J.—#›ÍzѨc’Ëg°ìŽk‘-diii!^–`rÝŒªJªê¦¯®¦ª¾–’€P$J4ÇuÄŸ;ŽC>Ÿ§P( Ë2ë?X;Øã/†¡QUUãX躊®«MiŠ"‘´çöJ”J$IÄãQÂaÛ6Ñ4e{æFÀ Üb±Ù~¯(J¿$9(²ÊÑGÍ“O>Igg'–]BQ$\lþû·¿áøÅÇ0cæTú2Ýôô¤H&Ëp]8ŽÍŒGñûßÿŽgžyš«®º’§žz’÷־NJ+øàƒ°, Û¶yøá‡±m›H$BD×Àu)K$‘¹Ÿê´Qб‹¶Çª¹&Ѳ(%Û¦7“#Ý—%›+ÐÝ“¦X°¶„kA)kbæ, œ’I<’@WãhZKÒˆW&q WVˆÂ1ìbªªJ¶5nìœcªÅ(j„ f_‘»ZhÞÕÆî]­´íj£­­ WWÈ:E4á"I ’¤2’¤`Û.Å¢ ÈF˜¡àØ&ŽeSž(GŽmR–Î,{Õ ¯b"„xÐP(„mÚ(Š‚®ë,X°€E‹±zÍŸ‚”À²¼GÃ0¨«›Ê…^È»Zƒ¦itvvRUUÅý÷ßO:æ+_ù ³fÍ¢¹¹™‹.ºˆ3Ï<“ζv674@? ÕÓÓÃüùó1 #`dEa׮혖¡‡)šILËB’¦¦& …===¼õÖ[ttt`+V¬`Ó¦MÄb1ª««‰ÇãTVV2}úôAóÙ²e ÷ßì•%Ê+ò8ŽãØØ¶…ë:¸®ƒ$ÑO2(Šo.—ÃuÝ€úT…PȤX,ÆŒ™3yùå—ùÉO~B< "º®#@úô§/ ì1ÇŠ¸Bu¡<%[襱­‘3.;‡)'ÌdÆGŽ">å'Ìà²ÿûeòªC¶¯ÛvpûÙ¿<ƒ®ïÛMÓ È£X,F(¢P(°páBÞ~ç 1*³ìÛvÛ¶I§ÓA”‹ÅÐu§žzŠ;[ùä'?Îm·ÝÆW\‚ºú)¼öÚ™2¹žW^y…|®H*•BUuB!OC*++©¬¬ ¢æX,F]]±XŒÊÊJTUõ´¶«‹B¡@UUMMM$ ŠÅ"‹-âÉ'Ÿdá1 (–ŠY–¦®ëƒ4Ö§GUEÂÐU4Uá„p‹h$„"ƒ®{>º¼Üc ZZZ¸ä’KxòùßKŸ¸àJé3Ÿ½A:áäOHË_Z¹ON9{þÑ"¤rf>O4!T&<9Aåü:"­)¦T–ÓqÉN‰rÜ%g“Ö;»ÚQÂá@I|ÁX2õãŸR©„mÛAfûöí\|ñÅA!g¿õÜyó ?§Õ4d2‰ëºär¹À,ïÞÝÂÅ_Ì?ÿó?S3©¢?L·‘U Û¶ùãÿȯ~ù8/¼ð–å0þü@H|ͱm›É“'“J¥p‡h4J"£³«‹X"Á†Í¹â3—PUQ.þå_î:2NÜbœ|ÊibÇŽíTÖT#—²ª" ™Í/‹°­o'§]}!êô$m¯ü‰T\%ï¥Xo¿³ŠûîûÇÿ>zÊéÒ~}®®ë¨ª01…B¶¶6²Ù,¶i3iÒ$Çá¿ø™L†«ÿ¿/°dÉ&MªfûŽ&ûÕ¯yî¹çؼy3¥’Åœ9shnÞTC|_‰D ¯ªªŠl6K*•Â0 …ÙÞ”ôЃ?>bwI žûÍ üë]?2 ˵‰‡"äryÂñ8él]í½ôuô‹†3ë™ZVFX6èz§Ô;›9®~½]=$k*p,30Í{k®Ïv•J†ü°a¼øâ‹|ìÔSF¨lÛŠó¥R‰ææf-ZÄßÿýß3­~o¼ñ<òs¶oßÎòåËyéåÿfÑ¢EhšF6—ë¯K¦PiÓ&“Íæ(//§P(P,zõÔx0U²,S*•H„#ôrHª‚-ÉÄã•Töõñ»'~Ë_ø Õ55$ƒÌöV>üÕzÐuR6 ŠF*¿§©{ ÊÊÊ(‹D"^ýuV¬X12¸~ðâç^~O}}=§œr ;vì`ÍšÕ¼öúkœ|ÒÉ´w´²aÃòù<9öXÊÊÊèîîfúôé477ÓÝÝÃúõëùÿøž}ö™ ž4i…BB¡|ÎÚa@}èþÌTW×Å2¹>¢Ñ2þíÿ·ßY‹-d2eeqŠ{±5B¦NJ¡P ££!µÕ£ÕÕÕE<§½½E‹±iÓ&ÊËËikoã¯N:‰Þt†-[ ¹LË.<‹l~Oë¦iá62™Œ—ª) …R¥_Hdúú²Ì™6»e+ÏýûO©JV“íMãX63šÐi™¨®„i{ѯ_]òÁõ1ƒ ÃðªBS§NeçÎí|ë[ß]áÀ/®Û¶DÊ¥R‰O|òÚ;;XõÖ[¼ôò©»îº‹»ï¾›RÑ⦛nâ?~ô¢Ñ(¹\Ž'Ÿ|’ŠdŸ:÷<~ó›çB …ÈårƒªNzgÕ>À~ì´Šógм«•ú©S±JQÓáªÏ~ÓtX³n²f+Z„Ãqá IÙR,Ù¶¥‘šš¦ÕO§½½¾lY–©ª©¦X,RS;‰\!Ïäº)„B!R½iR]it]gá¼E úøø9çÁ´2d l4ÝK“É2v·6£)GèÈŽLKc#º®SYYIg_'uU5Ì>ƒîînJy“iÓ½XCôf˜7oÝÝÝX蚆,Ëd2Ù =Ç/HF×uˆÆ¢HržÎT'ñxœ|¡Ä¤ÚiÔLšÊï¯Ý´ì"‘HÐÓN§1 ƒ|+®¸‚9sæ0iÒ$žþyfÏžÍI'„$Iüô§?eéÒ¥,X°€_|‘¥K—RVVÆÖ­[yæ™gÚ»+rÝ{ûjl²ºFx!Ër°,›¾L˲8餓¨¬ªòÒƒRá8á)N¡P¤¾··—ÖÖVòù|Ж’Ëåèé顽½=hyI¥RÈ’ ­}77nä½ukhooç˜cærì±Ç¢( š¦d¾iÚAóš—Ny.fÝ{ïñÀðo|ƒöövŠÅ"Š¢°mÛ6dYæ¨£Ž¢½½ /¼oûÛ¬]»6à©ýêšmÛ„Ãa à ŸÏcYVPyêëëC–e***6ѯ˜ lñÍP±X¤X,r×]ÿÊ·¿ýw,\x ét/mm­¼ôÒoÙºu 7ÞøU¾þ¯qæY§Ó›îfWK3/.»v‰†˜6½>(ú'|ôŒ§÷žÐ1 ªªã8¢?=óXšxçž{.Ë—/çé§ŸfÑ¢E<÷ÜsÔÔÔð¹Ï}Ž^x!è}¾ä’K¸úê«9ñÄÙ°a§žz*¡Pˆ{ï½—>ø€H$Òïʼ.H_Iâñ8ªê忣¢ÏøäùO¿ñ‡—.ñ0M“††n¹åf͚ŵ×^Ë”)Sxþùç½/(…B×^{L&Cyy9wßýzèÇäóy&MšÄ?ýÓ¸®Keeå :úí$ /üÜÊO+"‘}}½ÔÔÔÐÝÝt>f2Tµ¿NÙ_Á…BÏöÍ 'éZÐ0ÜãŽ?A¸®‹p „ÂQú2vloä¿~þ0W~æR$ $ÃÏ~v?š¢2gÎ6~ð×^sßÿþm¤Ói %o+F¡P ›Í<³_öµz`—‰ض ’‰„Fee ÿöý{X°`!ÿtûwÉdÒ̘1Ï|þólß¾ƒR*¿yîy~ü“‡XµjIººRTWW{µç|žîînTU%N‰D<¢'›¥¶¶6¨rÅãqŠÅbÚöíÛ ‡Ã^ÞÝÖÆäÉ“‘e]×1 ¯Ø·FÑh”t:M©TbÛÖMÒ¨À=ö¸¥ÂÏuý¤Úo÷¥ÝgMlÛÌ¢O‘ù~n`".„Àµ÷˜Èµïíwññ' ¿ËÃ÷áB¶oßÎ믿Îoû[Þÿ}Ú:Úiii ª@±XŒÎÎNÚÛÛ½Ïrí€õÒu=؆‰DÈf³¸Ïr]UÝÓä¦( ‰r¯àFƒ*O²Äb1âñš~ßeúôé\qÅÜzë­,_¾œ©S§Å_Èýj“o5R†>Íè—Xu]‚H=ý×·œ¾õó‹;~j··ܯYþ«SÏzúÝU¯^20²õ:þ¼Éû>Ó7¿¾éó%*ЄÁ“_.ó«{“&¾àx» cý}S6làæ›oö¨Qס»»;¸fànI’%ÜK’¤ÀšH’D>ŸGB”Kú©E°ÙJòL/ ~Å7ç%“ ²U,yóÍ7Ùµk•••Að¶·¹˜þù¾Ý0Œàó}ëá „¿ž¾µñ[l2™Lðš3øB:æ]~K–ž$öb`þë×~ý/äOÆ—6_¦=šâ-Ø»«ß’öNü{ù÷‰D"žoÓ4fΜIOO–³'ÂÍårÁ¢‹áìi8ùÆ,ÙAû©ÿ9~F Ë2'Øbé ¦ÿ»'˜ZÜôïoòxñD"1¨Š³·¿÷ÿîÏkàzù ‹Å p㯇ßS•Ëåú[s”àþþgìuŒ¸Whï]zVÉìgE¼²cÙàö/"Vÿ$Ý ¾¶êºŽk;û|ÎqÇ.-„Ÿ¦ôõõ1{ölvìØÁúõë½H1Ÿ# fm`0ä8FÿÂû‹â/?'ÇÁëÍ¢?¿RÉÜ'’¸ëÂÅ jª~d_^^äš~/ÓÀí«ë±¾Kò­ŸÿYþüýb€ßâ§8ªªRYYI6›TÐß;v5¸¥RiÐÆ.ÇqPå=RãOj`—¤æ@éõ%TQì~¼Ï¦óþ/çƒìWz{{)//'™LPî$™oßÔûó3t5¨C˲*~På›eáüß}Í …BÁwñ 'ý§DàŠülÂ?rö5joåðÝ„Wø Fß,ûêÓ©~™ÔŽÖó€vù­_·ZZ¼ä¯„ÿå…èÚžhWÂ#º}ÛF5ôAµH_B…žéCÚ‡õwÓù&Íq¯¹¬lŸ]èþf4?Š÷…Æ7Å…¼¼æ›îÀj¸.®³'•hný Ëß{3ðž¾Þ·þÖ4-àý©î@“¿gûªDyyù MÖ¹\. ÿ½¾õ³ŒP(D( ‚Hßrø,â﬿èÎ߈Öîì^gbü¡˜oÿû—ö—}Jyj|Ëy{ýÜoœ¿ŸôÑ‘ëÞö°\{ÎÂô>zŒX1¶“^°b”@|XÀŽf~ÕçÜQEçŸ0³|rEdÇÀىà …8ŒÀr æøÀA§Ó ó÷î+ÍýGé ÀxöÛIã~vâÐê;ÂBŠñ7©C0˜‘æ!ö¤îøÀÇ)‰aþÎ÷­¹`ÔíA#vžwÂLÆÿPÌ}Bæ€Í+0b˜3¢Ä0󘡀C¦6,ø‚a:ê¾j|ÔZ;*poûì)Òܺä8й?`ô‹˜Q,º8÷ wJÝii¶‡¿ÿùìïÞ1–ƾQõ?zËùÒܺ †<âo¬g'îØùâ a¶÷÷ž¡üò3¢_ãäÉŸEª:ó¶qàÑÿs¾tÅiGÃÙ‰Ciî~q†ñÇìga?`ÄaJ¹fÜ‚4ë[cnùS7ÿÍŸ(½uïÕÒâÙµÁÿØcˆ Gü¿cþâÃZ‚ÑkòȾl ÒÇVKRÝUÔË}@ÿÀâG7ž+<öÊâÝ­­dò&[ZRd ¥aýñ˜o 91ž×'÷?.Ašv«vgć7Dúׂ¾_`¥£ÿûˆÛÉp¨ÇðïÞ8|&ôØ8vÐMûª¹‡Áçö¿O4þµ@Š ÃŠíŸ#–ßû_õßO:úiÜÃi’ [segÂçŽ3OÌ!*Œ‘'ž—qæPóÄR˜ð¹ãÌsˆ ÀOø\˜€OžxHó}ä{„øÜCÌ2`G˜Ç¸#-$O?ª/ƒòS½¿•Z!õ"´üäÏØ#Ls?Džxï÷W~ ¦ÿÝày“aÊ—<Ð7~õÏ`ùHPܽ0ðýz-Ôß4üœã‹¡îKš+1š{¤Tvj.%¶ÿ9×^>¼€è“'Àõ>=ºga?,`÷ÖÜðœ‘ç­Ä= j^¡ p=¶üKG\£ø˜rô!d$­ÿe–Ç¢¹‡£Q<ß0ò|í ¤W}ŸÄÒ p÷(_Í= Fñm<çÖÇ®Vª»Rš×7͵7KûoðÞwÇ¿0à¹Ùûé Í5À®‡fÓÆÐ0~XÖöˆ°Êÿ)èyö05гÿëý¿Ç‡Ú+ yú£ãyØõã¡ï«Æ‘N~Ušw(€·ß (50‡¢0Ü}ö~œûH“þ÷¸û¸¸íC( çßÿ|=r¢e_Òf< ;yø=쀀UãG,°GœæÊ™zZÐù¨—r Û4<ópeK‘>òã#º]öˆžœØõ¯‚žßŽ/0+ Æd˜vÝ«­6à ·ÿ\Ðõ8™ÃÛT·×Ö&_yÇX7cM€;ZÓ¯_DúõgH¿>4Ðã lÙHžqD±àî›?!Ȭ…B”Ú`%‘9ýût¾ò±õä/nÿŒèzq+fë,Y=¸áÜ Ï5JiòÿãöMŒ‰11&ÆÄ˜cbLŒQŽÿ;ŽS;F]KÒIEND®B`‚python-hpilo-3.6/docs/_static/kibana.png0000644000175000017500000011377312652734620021132 0ustar dennisdennis00000000000000‰PNG  IHDR©Ÿ*Ò c pHYs  šœtIMEß + 0Ø@ IDATxÚìÝw\çðïe’„½7ˆ2àÀ½·VëuÔYkkõ×Ökkmmmm­vYµuïŠ 'Š KöìÜýþp•¶‚Ÿ÷Ë?ð.¹Ü=wyòýäîž0_E9SEû¿žª-3+?åûá»:5I¥ªü˜Òñ¸Ç„òS7nÝŽ»ùàï}Ù>Õ¦T A÷V¼úÜû¢ˆ(õÞ4Ô)<4² û² û² û² û û² û² û²TƒMu;µ˜{uýµn-;ÛKty)1ç‡Fçê84 ²Ô|3ÿ‰‹–ÎéhóxŠ·o@§ÞÃf¾cÃÿv.W6ª¦úvͧ¸Ù‡ÁgþîTo3íÜ@¡û”§—I_ù†6š°iÇ­$ÏŸø_ÜsÚÖͳšŠëH×'òþÉðEcôÁ†µ³šI Þ¥³¶ÿûë¯9mˆr¯ìûù‹ù³§¿3oÁOÛ"îëȤÕäå[¿îmËGl©×ÙOðÅéë—¯]¹p9êÂåËgŽn^2³›£˜!"Ýý£­Úv9ÿOÿ§Ñ[Îm™â!,·§,û¬ ùÈ'ÿÅl`h(#¿ö ;±ÿDȾ!ûoýñó íDLƒëÓ#÷A ÿ:yåÊÙÃk?èï"zÊq¸hû—m¤DDdÒé‡M³½ˆˆÓ¦ÆÞM“ã/¨wÉϼó‡ßs%Ê>üÉÐ!Ó¿Ýpðìµ4eiBÈOsFzgû=ެú.Z2Ô‘ÿÌàp2ìËÀô-¹‘ï[—IŸ\Ó“VžŽÚ2æï4é²"âÚõË×®_¾v=rÏl¯jŸ0øWÕøÓV¬~g?"bå¡3;whÛ¦CÛöf®½ßfñ¦_w+¿}dgØ}Í+~˜ë³Žÿe?z¼ßã£Tà<`J›œíÛc²_ÌÖ•†b§çé3àõ>†š¿#½Õ¼?õuh`W" œF,žßôü½;¶òáîD…–­òq|SWw³‡m#°ò°7z˜’Uñ»¿ûáÈ}> ~º˜ÓÇŒèîÏs—ËÔ<(œ†~ùËG-%¤Ï;ÿó»_^Ò0pÖäæ/ô(ÆÈÉ˺rAÊHûfò^¢ •š‘kkì’þíüÛøø-¾ÚÕõ¿©Æ«\±Tv¾úÇ„A™¾æÃEMö/|+àø—C6niÿû w#ùþo~óù`gV£/½¾êÃea%.ƒ>\8³“5§3\úã“oOd Ü}øÙôŽÖ Ç”Åì]úÕ–h^·å»§Ü˜ö憑Qó·}©ûdÜš^|:ÙßXo`K®n\´üŒtÆÆ%Æ¡q­'2=òæï£Õ5‰Š#×cÔñ·è“…,‘‘ÏèQ×~ IçœÆm©jÉ›¹c‰zþˆe±2j±p×WŠF­Hú¾þÁGÚ;K´w6}üéºèÇGßiÜÆ-í4/¥ï²ŸÞô‘ÄÞÑäòG}ßOîô~ùí ͬPÁ*3¢Ö/^Ùhý;o6ÿ6Þið[3F·¶76ÒÞݽìËíqJ™ïŸÌéïÈj eÑ—®J'ÙuŸýÍ{-Ýlrþðåï—Š‰ˆ„Ö§}>Ó¿±³Iñ™ß–¬<“«gÄ®½§}8®µc” ýuÇmÉ<+-_ë>aÕG’Ó‰-Æ÷–Ÿ7÷`£i &ø+ó3³S^\Í~¡elcbȽŸ¥4¡8öÄþGïm÷弯·ó§,yËÏÊxáÆ- –x2—&Nìw›Z+9âIœUÛßxc#oúæeÎo™5odkg«:óõÜ¡cï—L0æY4qµ ’~{LpË…åÞ§r ød€:HàÔ¥Ÿ‘ê̪àäª2’!ûøê}o·cÛuçòÕ-ÊyÆ•+d¥q¹ºúÅa~¿hkî°nSNôª÷¿½(爈x&Næ±ËÞøNøÕ¡—Å·jèê×wãÁ™Œ*%lÝÒG“ÔGŸ6™½ù×+·M›z»šÝߺ"ÒklO;GÓ´Í,ØzWëø 7Êaö“%œ°ÅÂÝ•jûÑÏ\ö÷Š}ðSVÅ¢ýTi³ ñ§ª¯žœaa‹¯O”¼ÝÎIüh?ô˜7†¿jäë'Šù23Šï5{Ùÿœ¶O~-8U+±s“Džo}?ÏqÛ¤×öß×›µûxã²O“F|¹ùÜû‹†5Þ¾í}ûg’xl¹wÚÀÅñ¥5W5«îìÜš¹yr_ûÓÛ3Y³6“òOÌ;WÀ’SÕhðªê«‰µ,~Õô%—Š'®ß2¿ï‘I+?DŸ'$Ÿ­¥ýȕĄ¥Mó·ß7—%o}oåM¹ÃÐß~ÑóÔGü§ ço™<å\1_jÊW‰ËÊB?žúC™Uï/ÿšÖçàÕ]YD<‰9{î›Ù¿(dþo¯]8£íÕ%WlF-žn¿û½G2õ¦oý±ðí”éß_UZþ‡G‰ŒQÂeWQ(+®ýö÷Љ}ÞÛ\¡hï—6rÌój¼z5Ö Côè^1ƒ"öB¦ßü¿œõZK3†gÔÅâö¶ÐT §ÊIÉ×ðíÛw³‰Ûv_KÄÊo‡©z51RÞÞ¢ï;º¹ŒoÝiœòŽã¹Öº85þéÒo¾[úák– ƒ…1ŸØÂ‹[Õdð#"Òg„üuÝyüO#¾]ÏIírwm»­*w UÜÀªtC^ø¦m‘y:N—uýV±™³¹àiïßéß/Y±pWºUUÛ[ûû‘ÍÚ|#_ÏérïÜ)1v2e‰×²¼g~ýáøþ~Æ-GDœ"ér| K†â{w‹eŽ®†dK/Æ•°Ä)âÂoéÜšÛIl[Yß;ž©#âJnŸWûus*/Ÿÿà„'“ËX¾µõ½ÃaZ"}qJFiMÇ#}æÑφôñÅ¡‹~ßìÙ¾ ƒOhÿ¯v[š|3UÉ[v?Anâb. N[¦H$|b„2 O-Wk«säÔâ^ ‘V©ãˆxV}~ØòÔ‘õ3ÊÀjTZ"ˆÕ2≠™ùÕ§“çʵ±Á¢M:¶«xó[–•”¯#ƒâþý¢Âø¤érrk;cÞ³K¸çy²V4ež¿õä¼ÏÜ¿wcõí5ZjýðK€»Lx¼u¯A#>ß5>ìí…r†y"apðè/Mâ¾]yïØôÊX÷««ÎåÌtå _}¡xÜÒMfs¬¡Jf¶ð܆|?)(âþ„FÑk>N­píeÅ œ1ó4GGßǙεӈ±}¥|/kþIªò=Á3kÿÁW½n.y34ÏÀs~b{kõ nêÛÝ]sgKŽÎȱý A=›ÛKø²&Vü³DšÄm³'„ûwî1dÞ/£Î}öî©òo:ªê« ¾§WëØ*w4cäTqùDD,Ë1|! z¶V.†UeÞÝrãìí®Uü—_Î|rG\;ÿƒŽèáá ¾ýçúü ß­n¥V¥nX¸'M¯æ*9“VÞQ@Ý£/º_Hím}D¡ÅùµõKqê¬G§Dø–M<Œ‰´¹YÕÿ²þÉ ¹R]=é·ÒTÄçBXA«)ƒ1DBëæZY×âi0ÕmÛó»|²`¤4lÝÙJ^VÜ@~Iz©Icg1FNÍ™òˆÈÈ÷ÝUó›\Z9ÿ½ÿ}üûÅ¢§ b?`ág>G?Y%g‰^âöò¤Žm&~öžüæuÑzï)_½ç~ó¯/X²9ª˜%"¾± ›yõèæ›“̚؈™§½™m\-D|ëvý›«®]ÊVç^¹\Ød@gcâÛ»³Ñ3)Ü“Ë/ßÍ܉W¹µ÷1fˆ;¶ð4¯Ù&à[u~wþ›œ$<â›ûö2͸ž©­rGp,ljø Ãcˆc9‘Þs¾ãâÛw{ÍæÄç³fÌ~ë½ïÜSq•1Cu‘&%âZ)‘]ÿÍÒçÇD†‡Ÿ ?9Aþ é‰=Žò"2Ä„Æ+«»Ð**äÊÕ±N`$ò…¢g—<“fƒFvq“ðˆo0q†güÞ‹y/æ‚1½üÉÚžˆ{¼b¼ü'jEQ5j¼Wö¼Ϭ÷êˆîzŽˆtE÷.X<ñ¯° ==Ú=|Óæ#?›×ÙLÏŠØ{k¾¸wïâG,üb]È”2…2ÿÒºEq‰ñk毘¿põá)ËÓÄí¿è¼œ#"¶àܶKŸüì³áË»j"ÒÝÛ0™Õç+ŒátMFøšÅ7Jko+ui‡7Þxëkû¿>Œ®týèÏÕé ÑÉYšG†’Ä[%Ãçnxk¥)O“}cß·íN×=qàEéó®†çÌúnßÁŒðo¦ýq…–ýv (nû¼n=cé\éýt“Ùßïì¨Ðñ„ýhæ ª›õéž¨í‰ yåVlEÅZqI¢tX…­¨ªÆc¾Šr®4iÿ×Sµefå§|?|W§&©U®Ö){L(?EqãÖí¸›þÞ—íÓQmZÍ º· Gw=àÖØ@D©÷îÔÌ‚¡ÄˆÔ*GD|±T¨WªŸÙÃùÍßñAÚìi;2 Ä·ýbÛ‡ï[›Œßƒ€W#mþÎæ¿Þô *ŠÚ¸üm'nçi9˜yuùּ݉òŽÌóux!†¯«šàÕÁéTGü1h”Ïíå´©!ûrü¶m¨R­'F}oë¢í©~ðÊÔ>Ê[¿¿5OüË÷ã¼ÛLúªÍ¤¯H£T‹¤~æ8#äóYß"ø!û[z{ãÇc7¢!àUeÈ;ÿÄ!§Ÿ4~h™XjDDšŒ+‡¶oÞ¸72CûWý ~Ðå_^y=x%#ZZJµÅ -"²ÔSœ^Y«D;ü[<4² û² û@«+ã|2 ƒõŽg¨kpÞê›&ž¾hd?¨ÿÁñ \ó õ-ø=þ;1áŽg€“ý^T‹Z^`ð{éñÇ3Ô5¸æêgð{öt€†æÅ_óùïÎxà< ¼ðà÷xníŸýÃñ õ?û¡V†:’ú^büÃñ u Ã0Ìô·ç£!ê7Üï€ìÈ~€ì/ŸMðªH$ÍZøÚÚÙØkPµnùR^W£Ñ&&&;–Ÿ_ˆ½ Îû½2Á¯[Ï.ŽN~/„V«•H$3gL433Ek@C€ ñjhÖÂW$*Ëʺ¶omkc€zàÈ©ˆ—øê&&Æ&&ÆIÉ©ƒöÚº-»ý N°µ³!¢.A~/’µ•ÈÑíÈ~Pgö“@@Dv¶~/’‰‰1Üï€ì¯>\ó #4¶0=8!ÆjÅ ‹ìÿ˜ÐåõyÚ˜²,÷wÜàóy¤É¹¼ûÐ-¹¾&s@fj&á3§²š²b…¦¶Olbj,æ1Äj%%𗬡‰µ¥Q¹üÃ*óò'¾ÛÕâÑ„ä_o‹S×Òúd¦–¦bC©¼¸Tcàê`ö: œûöQäO?†$ªy6=ç,&;½ì»í)º*mÚ¨S¿®[5v61œ¦05áʹ3G/Ý/«zómzÎY2¬ü K¬º03îú¥c'®$•þ«£D`3àÓ†ªvøÃ9WíY5úÞwôõGrV/Z­&øO š’âRƒ‘™¹LÀÔÕuäK,éΟ‹÷'i×üÆ­gLl|;Éþõ‰Ã˜{£K 5ôÒb÷Ñïr×rƦB""½¢ ˜•Z›I lYòéõ[/ehj¸æÉš¾>q”¯Tmà¾Ô„½³sÓþ¸²—‘ÿÇLéb\”¯,×Úúìð‡NmÛmýæH?)_+wÄ ,|‚úõ ja/~{Š’#ÃN…^ËQ×ðù‡Ù/µ³ …¶fB¢g…FæÙgÎ;= tÙ±·N_–ëÄî¾Íû¼Ñ¬K›åkÂSžºYº„!— DÄÛºûõþqç€?o IVqèßþN¯1èS6ÿš9dn'#óûôîІ€W«HݲeÏ©»E‘ØÉ¿ÿ˜ #Û;Š™WeTië×kßœý_§›ü‘4yX€³0~Õ§ë®+Ü» Û׿‘_“{:R˯µ^E_à0tjo6¿GG&£Øàh‡Ï xåésÎ_Ó’E¯ùsû5~˜ò-GÍŸ2{åÓÁÑcš¶3­ÛáaåÑ'6\Tê9"‘똹j¶Ár/®Y™ðh$KâtŠÜù†Õ•éaíÔ¦<™G‡î=Z9™ ËíF`bmÆLšÑRU’rþèÁk…µ#çžo¾ÑÓ…—}nûŸÇ’ËX"V]^³¯*´òqæQYÜ…ð$¥&?Ï@¬"6üp™Tl×¼g -Ϻ‰‹ô\vIMù{ñgƒæ.Îb*MI•Wµ÷ty‰÷u]Zº9óR «¹Qº‚¸l¶§«£„IåìΙÚG{-dWD†Ö"`ðÀ1³ Y‹vÇ‘ç¸w‡äœÙôsL.ϦY[_;ñÙÏmà̞ѡG¶bíÚí7ä­a_l¹ñàfE×¾Ó{Å„Þ~†³è? ïÌ)š%?ÎÔñ­;Lül\“¢¨ãëdª¤Îíöõ±Ãúo6],dIàPå:ÄꈈgÕúõ9bJ¸tæfQZššgÛeÒüQŠ®]™®6iÔåµ^¦ÄeÖÎ-õèØš•›÷·sð¶wÇÔ º¬ÛYDÆ-;yT8½Ç3oÕŃnÄ¥ÅçëÚ™Šêòl‚fÍmwÍ/»kçBONW’“Uò2³®Èµ×¸Ñ.w¸”­ª"!:Oêák}.W_kûÀºó¤Áo۟Dz¬:÷ðŠ>{½¨æ³'O,—u1<öáè)ú´èói$p”¶´µ ¡´&ïYÔÀÎ•Š‰4O7–Õ(4Db™˜GTÝ@kДi‰D2C%Ù!?~uLYú`éq Çïùvp&ª=½dº˜Ó‘wÕDiI±W‰ˆ2"¢üˆ•˧j‰èN‚ÒÉïmŸ.¢ DDTxåŸC’5ÝJa¾Ü­«Ó‰í©Z#÷׆xñbw,ßt½˜%¢øÛ÷”V_¾>¢Ÿëµm)}Õë›LDÄX2aK~ ÉÔy¼9°?eÿO.æ³D”Ÿg²äý¶µøVã™5ñ3ÇÔ<È bL|ƒÎ@µ6Pã¿.”­\¬m­%$4wvoLò¬ìM¾EËÉÓxÉxå"§/º¹á÷ÈÚÙfßþ}›§ïY‘ äªj‡^cD†èkqG÷î$ÜM¾²;4µŒŒ›úø¸$‡_/ªù×Õ+óKÉÓ”ñx}Â[]Ôꤓ[CsMkm.6q° "¶¬HYƒCœ¼øìÇéT"™ñS+Od,&*RjÿÁFñÅ2‘¶LËqºÒÒ¿[O‘_J )_Ÿ•œ¢î0yÒ˜³W2JË¥öÒ‚âG_©h‹óÔÜÔøÑÉfEN¡öá!Èß»]@ÜŒy© Û¦^2.%2áñà2lQÜ…ûô†·· %]_õ:<üÿý ‘Ù_Ohåí%£´ƒ±Ïp²z­àß9µt¥+‰×B£å¾mÍœúœ ¡‰D’ƾ6uø¤ŸØýõ™#3DDÆFyPnÈÏ5>;Obe–òí77ÿ«Qà0èÝÞ–µÒNŒÌkÈàü nJ¬*ø#õ4Ì?ûèïQEµZ$sšŒˆ½®C-¾®>7únYû622¶u3&ƒZÆ#FdíÚØíáÉ6õVJMþ¸Á‹Ï~úâ´ -¸»šóSrŸØ‡Bë&.BRÜÏúã×­¼íy$¿Ÿ¥âˆˆ'sjÓ­CûÝì-d""9C\iì†å»åÃ{uõfQÚŒ«'6m?WÅh2qOÛÁœN¥%ˆ ñ$¦RÒ¥”êÊ T£–+Y²2•ðèiëðè[Ãão¡xR3 ²‹ÕŸàÅà[·Ýu×’³‘Ë¿¶zoîˆ ' c(¹¶ñ‡u‰YõzÝWV‡W^soÛ²ßMìÚLžÔ*k÷Æ#)¥r¥Õˆz¼³8VÏð Oî;“©«ê”ŸØ¡ýáÎw¶¬Ž/­érÙ ,dmÙˆ’3´•Ö„'sô0Õd)kççätiaaw[ öñ[tì`mâiühnþÙ;%uè7ªC}ÿÜ-u@`Çn®—v'W±•‘úôlcEг3µÕ]#mÒ!ÈœŠÏ\ÏÔϼՌOÆúå]Ü{pó–”ÜÓ®ŸÖûÁ‘¥Î¸²ýç+»dv~úM|mÐleÚ§{”ÿè+K)q¹rK¬ªDEB'’t IDAT™€¡Ç?P!6•òH]¢bŸ±•±:•–ø"1Ÿ!¼Œq«©ŒÈøjOâ‘çáIjå£Ê²àÌÞs½çõp¬«§þ8ƒ²¸H#P¨9­¢°  HO"«ú¼¯´ég"ÒÇ÷›±¨U;’!åý«û7†ß¯…ßxÐe†N?qnwiåk‚9}I©}— jk°Sù­ëÌ'Méì&$2iÚ{Ð㟕(ººcGXFÍÞZÙSÅ:‘Øêµ^3Fdþ¼û|Ö£l͹u3­­T³+$¥šÑÚNœh¬‰ý+4CK<Ëæ]ŒÓ7~s༜#"¯Ò9E›ŸpíØÞ-§&Mv!Òåݹ˜ìÞÜÛC$Ä*2®ÿ¹ý²œåÙ<;sË/ìgÛ×ÝŒ§Ë¿±vûñÛe¶!7|ý×Ê>£ú÷œÑ^ÂpÊ̘ð5„^-0ÑÓÖ¡ªWPÆì\³•5tä´v¤ÊˆŽØóëÞâxxáøVmg.ù@òÓÎt;¿Î¬•.3då÷`P'¾3™þö|´BÝ7dØ "سóYHïÞ½CCCјPG9ADA­[¾ô5ùäÓ%ØPïñÐ ‚² û² û² û5pz½žˆrróÑ/BQªÑhЀìuE^n>…G^Eüx‘UV~ABB2Úšà•p'&ÎÚÆJ*“^¹‹ÖøïŠÒüü[ë?‚7¢5 !Ày¿WC©¢ôôÉðÌŒ,½NÖøï„BaY™êÕ ŠÐÐ0ÓßžV¨ßpÞÙýÙ^>AvVZ ~cò‹åh€ú ×| û² û² û² û²@C xölyA>Ú^ 3+kôN/ª|<÷ù:N¯×s‡Ö€Å0Œ@  …IIIè^`ùôüì§Óét:ÚjÇqÕïpÐ;T¿|zþý~z½ µ©šÝz'€ê×EÏÏ~¸˜ jY5»ôNÕ¯‹0Î'@ý‡ì€ìÈ~€ìÈ~€ìÈ~P£8ƒ¿¡PÊ'Á‹]œ¡èÚÆÝ1ƒÆô·SDìØç7vJ+3~ŶÐ$DD^»•V¨d#s'¿VíºúÚ18JêCá¥5 ¾=¦ëòþ7sºØ ^õ­yQ½[špéô©Ûr2<¼—½°ÞîÿÇ-æ(Ä» ”O/ø¼#¶rwwu’>u±Ú¬K›v…%½ú¼6rúè¡ýŒïŸÛ»>ü¾ªB6få·÷¯¿RdÀÑð²pÅí­¿Ëä(ïìóWžÍÕ?û᪔ˆcÒÕÞÉlIlØñ«¹ºº³A/¬wŠ =oÜmÔÔùÓÇÔãàW€W«|zÁê<©[>][˜ó«ž­Ï¿pêZ™÷ÀI½|ll¬¼[õ˜8¤Ý>y:«üFJrKt8z^CAäoï~x¼ñ[o4…ÿ±9VõŒžëÞž/ÞÿaÕwÿûê@’Š#V~í¯?^ùûâ÷ËÑבmzQ½SAjÔ³y3a½¿Xá9-¯Zùô¢ÏCjîmÙpÉ}ÔèN¦UÌÔÞ½UbÑn“¤\Ñ$²kÑÞîæÉ[9½EDDšäÓû‚cK5Ìž•7Œ\»j~wï1Q¿·z9‹‰ˆ-¹²oO\ÓQc\R6ïIk(»{;%«DoáÝeXO >§ÎŽ>~öZ‚\GRÇvÝ{ut2âJb"BOÞÍÓ0R‡¦‡tllŠo±žÝs­Zðó]§ÆŠµ«¹éï§•[ï6>¤‰ÑSŸÁ*oÜÓ‘æöúËÇ;]ZšADTs#SÓÝNP'bÒ èt©g÷îKÖjhßÊ;<†8FkÞnìïŒ-{ÓZ #ÏßU62«]Ñö=÷{ ã2‹ù®½úú©.‡_ÉRh$n=ô °0$ÝrÜxÐŒÎvBÒç\ر!ÍoúHK>iî‡þqV6zTKetÄ©Iy¾¹{а>-mÕ·7–[þì^Žì“ÝÃUVÝ=¼í”Ù éí„DÄ_Ú³7¡Å˜q>RíO!EÅÅv7I¨ÔU굘O“{ëØé«±ù*[z·îÚ¿¥ƒ¨ôöÆ=É>-$ñqù¥Kß#;ºsèoåSÝ-ŸjõT}I^™ÐÚ¡ÒDŒ‘­D—QPÆ:‹xD$nÔ}hÿâM.#¦µ¶ài¥^¼CW•N~RF_xçŠÜ©Wccž–XeZtÙà1cº©Sï qpã–}äð}‡áïùšé3.n wÓÇ%çÜñ4Ûᓇ¹òK3r F(Džßs¹µ]?_ÄÒ…Õk˜Y —Înâã(yzÄ·íóñ—ÙŸ- NaIs'xÝ“%­¦}óv+Ù+q~¬z½“Эëð¡%ŽYÙÑF@ª˜½›Ï=è¾Ë’Î$ö:ÖÞÜT¨-b•¹™&#&M2)¾ºw}pXÓÞÃgà§Ý±'"Åçµ&N^¶ª‹I…ííìyl²Š_–˜XÚ²­™!'>ƒïÚßBŸ¯vè5ª§‹0ïlðáØFUX¾@•´ï‰ŽîÑG‹Ä½¥«æäíÌ ;7!é‹î^/±ïî&cT÷žì=*®6›~üi]%§N 9tYøÚÜ‘6¼âØûޔ޿@¬23^?xäØ^Feq;¶Ÿ=çéÔ]ƒþP>ÕÝòéødÙ¶4ɉŒ/1.#ú®Á³•›øAnµlÕÌQÊ#žÔ) ‘ +!O‘~+IÔ´«—¹‰có6²Ìè|1|N]š%×ñMœÍE8:ªÓs%j¼ÿ=š<»çz’LšMüzñkå¾WjúæÒO¹6”aœxfþ]Z{ÛY˜‰ù  ̼ÜÍ…$0w²3V~.R#vp· y~©Œ|”©I¥¬¡$ùžÀ¯»›&.]Éê‹îf2šXŠ¥n]:µld*Hl›ºɳúŠËWWÙÑ="¶oæÃ¤^ÍÔp¤Ï‹W»µp—êiO)¿ÚOï*ÕÑ÷M{4³5â1"K﮾F)·î+9"Es_)x2‡Æ&š¬"-‡þP>Õáò©VÏû LmdºûÙJÖMTþ+eM^®Jha%{Z囵°»p9&·‰ý壀aÖB"¶bÙ%–ŠØ|µªL­+M<œÁ#"ât*¡=Gb—.#Ûž ÛvÎ`ݼCϾ~V(GžÖs­Œsõ/×sùNøöóáM$Õé€XyüÅ«Yÿ_Ÿtùjz_·ê=ùåû—½ÓßÐXXÕƒa6ÃÇr1‡fVŠë /m ëÖÝDZ4òZ¦Â^ž¤wìk#$Ò¦ÄDÝIÉPhu%¥®âòYMUÝß„6^¢-·ÒUŽ’k‰œO_{1±EO{J¹Õ~zWɪJÖÈCòð¾?žÔ\BI%jNR~;†8'B (ŸêpùT«ÙOhéÝÜô楙-»:?޳ÚÜ›²|_·{z‰ÀÈz?q:2=ײU³'`ËŠÕ|cccS™ØÂûõþVj0¡k«^“[u-Jº°õÄ™·aþÆøA €J=WQäªÏ~¾¢•Ò•óGØýG=Wñ•µŸ~’Q~š&fÓ'_rß|1ÜóUˆÿ¶wúW©›§ù©ø{1GW3©©—mItl¢ZíÐÎAÈ)îÛeÜ»_¿^Ö‚¼ó;¶)*§LIÕÝß½ºµ¯¯Éî[wîI…žcl„DTåSØJKf$•»Ê‡ƒ˜òŒŒ%<\e 3±J¹ŠŒL˜ªäzr!èoåS)ŸjôšOŽÕ”•”–>øW¦cI`ݾG+£;‡7„^‹ÉÈÍÉ˼{ãôæý78ßžÝÊ•ÎòIU¬P•j9"bDö횊Rî–4 hô÷Õ¯†’Ä´"-Ç©³£Ï$ó¼šÙÊ›7Qß<{·PË«-¾›¥åôòÔØÌ2= e&R¡@$ x‚&þÈU—y?ÿ8«½Ý?ôY'×=ì¹$-¦ü´öË!® ‘6vëÆ+Š:ùã¦ÿºwz1¯‰«§iÞµË*ç¦æFl×Ì¢àÂM…ƒ—ˆ ŠÜ"Ʀ‰§µO[œš£dŸx²¸ªŽ®üø¦MÌóÂ/¤Éš6µTë)DôŒ®ÒÈ©…‡.îl\¡–#mqBDŒÚ­…³´ªcý- |ªËåSž÷ã ®ì_uåá¬ÚÖÚBìØ~Ò(«ˆ‹×ŽˆTs$2wòë0¬[3ûŠm$tjå# 9üs²U`ß!}\X¸ØÉemE?pia«"rËxæÞíôqñ·þƒ…í_¦fDf.MÛöó$ƒª8.<,DÁ2" ß.½ž1Ø@CÆ_ZºÀå»cÛœý½lØ×Õ﹈Hà8ð®~º9¹é´ï>äfĸ/YLŸ}q ¤Ãœw‚Lëdùÿ¯{§ƒoâê-»pÕ©‰µˆŒ\½-uäç fˆ±màräÔúÝf2 wg[iQåç2FOvtL¥héÓÂöÔ)}€§)¿šO!®Š®Róè%î·9vúÀOájYxÒDÆ+­¢UÑßʧº\>1ùÅògÌ–äÛÛÛ×:Msxç%—a“Z=¼â“UÜ^¿íŽÿ¸‘&ø^à?S]]2ý›k*"FÖtìç †ý‹ëÌ ª2½X&~t-§W)Y#™èß¾A³³³Í¬¬_Þ P>½"å“à•hXƒ<îbžm‡ž¦øa€! \°eï[_"+ÿeÚP>Õòé9ï Îû¼Øò ¿¼ Pÿ!û û² û² û² û²² û²Ô‚ç>";;Íuz'€™ý<<<ÐLPË’’’Ð;¼Àò ×|ÔÈ~µÓ)KJÊtlm½žMPté—þtÉãíÏÇ7—›l(¹w.äHXTj)É\»õØÕËŒ_³kƒó~а°òK+Þÿ«ƒéºÚmCQÔæ~?•ZJdéícË£²´«GV/Û™¯Gö¨©³èò¶]·ÊˆˆÈ¶ß´©ÓæÌîíÊ'"Õ=[/äjòµqÍ'4x†â+ûǺh> âTi{wŸ¸ž©â™5ê0dük-d¹‘»·½žYÆ¿é´Åãe—+<Æ;oóâµyÍZŠâ®§•9w;uh3S§L:¹m{hl!ÏÊÅ\Q±êÈ»žôè¿Ü[7~«ßo3k~?‘fH‹¸œÓa€c•#¨s ÓgG¼(l;ÉÁ '¿»Ák¦·™úÙlwÍÍ­¿lßéjp!ø–tØü%~ÅGV¬¾î>a„KJðwãöAbÙ‚BûióßÙ°<øÀ¹ Ÿþ–Iû7K´0kzsºµkíýòéOW˜Z@ä<ü“Y& 1ñuü† ‹á8âˆ3ˆ'¨:ʼnl›:1ÑÉQû¶F‘m§i³[0šÌðu¿LÔ¹4µÕßì÷äoÏ{xx<÷Y™ªü¥·6á}¶ïgKøb´À3h2nÜfšÑÁÃHjÿ‹Ž3ºÙžÒ;U³ƒz¶s¹7w¥œªÍm´›,j9û ŠJ ?)îN ŸˆY:´ò3½yàDó1A¶Ê„¨XaP_×{÷ 9Žtê’ìø‹‡šíë_ù1=Í«HX–Mù—î^¼“kãRp3A^a&ϬEÿöÇ~¿ '"2÷já&È<óׯ‡ïéˆÈ¸Móš¼é%g¿J…T•ÅÖ“ô¬!W]ˆƒõÙ8ŽC#<û]¢))“6p•òˆd|Ø ÅZz˜ýžŒyÕì žM¥×Ôr÷År,ö4@ÕŸË16Ä‘,èÝÏO¡ßytóOg9‘µwÇÁLÞ[r×ïŽõk ïÞr1hþ ŠVun1m>|Dà†[¾»eéÝÎÛ‘_Ta®‘ÇàéC Û§¢âs¿/¾D:‘Q“Ó‡zIkô$\ó #µµãn&åh­Êä˜,‘SKœ+hxfíæþØ®òÔöcæµó8ÞŽÌÓñe–ÖR­ˆ‘£±ÀÈ´ÂcˆhòÒþå8pÁüiÓv܇mÇ=œ>lD¥DäÐyê‚ÆÑçÂ/Ǥ救ÔÊ¥iÛÎ[¹Èjzðd?h¸¶ƒ|N\·NÉòÌµÚÆŠF""‰÷ÐQA;ÿòùÙ5ë>edKÓvVŽ'qlÕ{L«Þµ\ù`¯@ÃňZ÷›Õ • ­†¿0¼m5¨ÿýýÙýàåÃ8ŸÐ0qjuZLI^!+²’ºú™š×ï_úEö€‡Õ%¸¼«°ˆ{4…/ñç=t€©„©§›Œì §OÝvã¯Ãª  ª˜Í7 UÓ‡‹*Æ?VshÓ®sIÅZ2vm?üÍa–‚çÍUFÿ6ÿ·h1>[0ÄYˆìP‹î§W ~d퉿ÜÑ¿“S>ÛEm\ÃyƳ½$Š[Û¾ùk«§×;þÆÌ3çêsïäºÿöý.–ug„Œõ KDNÁSç•^½¤6T˜"tê9mÖ OcñÍ<ül9¹\Ã=g.+¿—›rð»O>œÿùòí‘YZ®l5Îû@Ã’ª}ÆÌ’4$üÇÿçIý|ü©Ï ËuíÒÌœ÷œ¹<«®ÿû6Hl&ã©ROþ¾â·ƒ_Œp{Ù×|â¼4,ÆÏŠABc~•£½Š®m_á0nZ'kþsç2™¹LÀOêÖ¹_eLl¡á¥o5²4,mLùOÇw g3 ·§).2¨ŸÙOŸqü¦œWpf×Î Gofh8´;@mª 057n3͇èàa¤Š?µÿÀEÇÝl¼pRRö¼<†Üó;Ö^.!"âYt;²»-È~ÿ§))“6p•òˆd|Ø ÅZz˜ý<<<Ê?Qj§ÍÍ‘t›4¶£%®Gd¿ÿŠ‘ÚÚq7“r´ÖNerL–È©¥ u¾8%//~ï–+däÐu@€ƒFd¿ý¶ƒ|N\·NÉòÌµÚÆ ×T@ ´ï3ab?‰„)K>ºód¸Óè>öŠýþ5FìԺ߬Öhm¨k‘TBDdìØ„w4CÉÚ?— 4\iAæéä‚ ½ÐÙÞ©‡›©´^_„o¸ˆˆ :–/â=îð+ÝŒ4Pß>úKï/Ývôó9ûhŠÐÆké}çºÕ×aý ábËÒ£ÓÅ>^6ybdªÌ·µ·û4œ*ý£•;~Ì­0Q—ÿþŠbÅã>wV, XyÌ¡M»Î%kÉØµýð7‡X ž9WsãçWÅhË-ÂáõÅ ûÙ½Ü{ßý ÷ûmþ­3¿†jx«f]z˜c´O€áÖéc•‚ߣâ wѶcßoãÅ/Ÿí¢6®¿á<ã‹Ù^Å­mßüµÕÓëcæYs[Íùeõ£§—\[»ô¤g õKôÙ.¾©G¯½Ð Ì–ËEO—½· ðÛrß zN›åéiÌ#2óð³åBäŽe¿çÌ%MòÑ}÷[LžlóòǻėÜаܔ?cfit±¾Bd’:ûùØŠ"ÒçF…åºviVîZ¡gÏ5äFì¾j;¸_£ºð+wÈ~аXŠž1Sh)®2%Š®m_á0nZ§ª.߬j.§ˆ>¡é<,°nÜW‚ì ËP·§_)vdóäqºœóëVž Ÿ;¶¥¯šs5©Ç‚“}†÷p¬#7Ú!û@Ã2hPkϧÌjÕ»CiÅIœ:õĪß.9Mœ3Ü×äa€â”©Qçc õUÏ%"2ä_ØiÜopSY]Gc½@Ã"sí2®¸Û¶»§{´{í`ëŠ÷æq%×þüaoŒ–b¾›wàÁ³ÛýïÛ7„çƒwg lêÓ"¹Š¹S¼E¥1û+ÛÏèPÆxAö€†Šß¤Ýà¸F~kÎÞÜ{¯ C'tvpÝ)pª·ù¿ö˘¾óøÊ÷í ""²¬r.·˜¶´EÝÚfd?h€cÛÆÿÙø fƒq¿² û² û² û² û û@} @@ä)V%fh‹õŒ¹ÄÓQ(Bö¨OX¥òTHvH¢Ž{4…oa2x°]WG>ƒìPpÕ¡-÷OV˜h(Rì߬UOríkÏ{"þqʤÐ?Ý_2ø«O»[•¿q®ìÆÏ¯ŠÑ–›âðúâ…ýlÊîÙ¸=,AnX6í=nB_/ã—~»²4,Y—²+¿Ç¡ðØÑâÀI–6¼ 3Ïm^u8ÏBXÅAY«9¿¬~ø7[rmíÒ“žÖ”±æÏëg}=ÛSR³sÙêu– ßigþ’ÓÆz€†åÊmíSçåÈos¡*¯ÔuÌ'ïô´ö™3MòÑ}÷[ ïhCùWÎd¸îÓDÆ#ž©oÿv÷¢‹Ù—½ÕÈ~аd–>c¦>SQ1ûñÌ[öïãg.xö}€†ÜˆÝWm÷k$&]aj‰±=+ÂY IDAT«øÁ©³¤8¥HìP›¤ÂgE$©ðŸöÂ)¢ƒOh: 4¯» Ù@›¾í»mwJ84@ƒÐÜáééN$ñ³üÇÙO“z,8ÙgxG‘ÀÒÕ¤4-Oó ´àT9é*37‹—>Ô ²4pœ*õÒñ4‘”¦h(üºZØ;|ÒÓXj I‰ýäxNÉ?8¨¹¤É;+ÊbÂuî½ÿýóŽÊˆ›ŸúÞPsÿ/u—³Ÿ.lÌ̹c¼uÙ¥-˜‘ÒÍ•f/ÙºÇ9õ桇÷±¦èU_lëP°Y[‡s‹àösšÒtôÝWvzè[7Åèºö1¦¡þä÷wžÛø§¿¾º÷ÙïÎŒîç tóãõ±³îœ‘bð:ìö6ÛÅÿ¹”k¾JmËÛvXšvSfÇz¸>z¶u)kdÇ9È16ùêlç©ÙûúŸ¶ÝûeãÃ/}­>*%´­¬Îuñl>ÍQSáOPjN(hR„BN0.¸º°ÞÓÿÓ¥n>_©?¾å%­Ÿÿ%qéS‹‡›:K~M'wæX¦=œ$·\ùXqq1k€ÞЃ­Pc¿šwø|m{%?œ‘zùŸ4géÖ¿¿–—ñ¥o-L·|²7K³—>Ö6têè˜É7Úº~ëÙáw ²Ú´±fèíã"õ­»6üc»ãûOÝœ¨o=½ë€5aQ\ÿŸüÖÍìç©Þ½¯Ì0bÒ­IAŸda]h|çï¡¶ž)¬o³f¿þ†Š£¹M~{¥séâ qz!„HOO' è=Ø:€@eÊÌøÏg/üOuóåY8þ›ËB.ŸAhÖ£ÿøÝ¿óÝ"ÿ·ß]#„"xê÷~óˆaïÊ«n9ò¦˜Y_ûJó›oþè;mrPTƬ'¿<%R–#}õ®½ñÂ÷W)zSxúÌ'ž˜ÙÿwžêæÌHÓ4CìôY“ÆwýèM9|Êý_šr16ÿçã=÷pO½­['¸ä¸Eãž“¸{EùѶf·."=rò’´“‚®º§6ñé?¿rõ;<ô›?~ò_ác–|ûWK.‘9ùæ'~z³o-s7³Ÿ1nBšk牒È!ŸÞ1Y2Å$Dš™kè_l@÷H¦”Øyß‹0 ÜÍìç®>PÐ|AÝôöÁÏþÔ3j䈬/ÝÏJà:øb['²ßO}÷í“/½]²4ˆ[öèÿ['€^Ì~²9.1I»ìO’N¦Œú['€ÞÌ~®’w_ÞTzÙŸ’–>uGUèglz3ûé£&Ìš2ÄûÉ¿•ù§,Yƒ”@¿oÌØ:ôböÓ…š8ñ³iVSùŠóMJŠ…›hè_lz3ûikS›û“SjT[yy“]sª”@ëáÖÉ]ydǺCVE Iž°ø¶¬Dv²ŸB¸+Ö¾uÙ5¡£oçJzú_¶NJýñõy–ù}yˆ©íøšUÛÎ d¤…;²Ÿ†¸YwÌkýä§tÙ›:(ÌÈD @¿ëÑÖIuÃcéÌYx5M Š 3°=þª›W@—ƒS†edÄš¼mÖæ6.(ˆ‰ߨ˜õhë$ÌÙS¹çÕ¿½›mÈšžÀa Àou÷2jkÑö×7œi»ø¯ìCãîº÷Ž¡" ßõ|ëdH¼éɯÍݸnmþ ‡Ç…^üI¬¸¸˜šΙRû{U÷å'šò%Ê–¦ÔX› m.Δ9̬óë`ÓÍìçm:¼çœ1kþW§&‡‰¶â›Vï:95mjœŽõ@¿êÉÖIsÕ•”HƒGÄ„>lÈÐàìŠ6åÓì—žž~ųIƒ€ïóxµ†fOŸf?“LÙû¬M¥/vjŸþE—ñ­‘ÉÃõþ»¹ÁRÚªáYYCb-F“%jxÖˆHGUaÍÐßz²u’„ýÜ–GÊ]šð4ä·F%‡qK‚½ù쎞»$ø !´ªÚ3?ñõŸ¯©ð\û%ý¢»÷÷ Š1µž.ªËš$\Õgη˜ƒùÁ @¿ëÑÖÉ”2}aÚ–U¯¾æÖ™ã2g,É ævAÛšSe•íF¼Öâ—/Äÿ6Åré¡Cš«rÏÛ]_Ùþå<µµ©ÿæ¿fEÉ]}É€È~ú˜ÉSŽm[ùû}ÿmzë‚x~'Ðÿ³m$KƬ%ßšEù,Õ;í>v¾²¶&9-ñ’̦9êÚR|öï?^wõóÕ–sgjKÿöÙušiÐ ‹–Ý;uQêü%#û 9bÜ¢¯G?[×&' 9&‰Ý~|['ÐU­M<èjkPE¢îÒYÆø…ó…pä¶?‰žý½ßL3…ËŽÒ_þãKkýì¾TC§/é¯ÙRןª´œ;XÔ캰äQ³æÌ^4{tHEþ™6•U@ÿbëºÅ`ì,"ÌÝ:PSÒGë%![RgÞ–aÏ?Õè£DéröÓœgwíØšSbýl6¥:kŠŽ®ßYæ`ÝÐØ:€nŠÞq ŠˆÔÇ4ÅíÖ >{ô./•·áT…'a\Fäg¯ÐEŒ½!ÆUv¶ÖÃÊ ÿ°uÝóP²¥ƒ‡BïN éB̳—Ú›ßèš½d߮ܗ&ÔÖ¢-. ¾iL„žwÒåóý4Å鑌–K3¬¤7$ÓÃqUú['ÐMºŒô¬o:¼TãºüïAsÆŒ[rõ%¼5;^yeGuk­ÓZöÂÏ÷ ¹ýéÿ¸¡iïÊ«n9rºÁÝZ´öÿþýªS5ÄŒš÷ÄWoŠ–ÛÉÔÈ~΄]Î~rp|ˆvôlcXJÐ'ó-gyQ½<2˜»èGl@÷'A·Œ¾13áÂú µ§l.·Î”[r⸠];lêãç|ó§s.ÿ[äC¿ùãÅÿ¾àÉ/èÊKú[—³Ÿ>rìØè}{·|ù“9uƽS¢™\èWlz3û ¡˜p×#éåçN—7Ù…):iÈÈ”£D ôû–Œ­@/f¿‹3¬äÓ’©Û€×änýÙñW©CçžËz2ÒÚÑ£Åõÿ޼D•:÷ÌØÇƒbú(ÿ±uè½ì?¡hJ­³‘:\³J<ªi5¼&¯ªP_ S ûÈ~²€ì ûÈ~²€ìd?Ù@öø=%À<5Çw¬É)·*ú¨ŒiwÏ©£&À?±ß@àRs×ÕÏ~øËßòŽÌúý›‹ÔýÀßHæäywÎ" CxJœÁa÷hýÀß¶€–¸´X“$„pVçVXF¥Kø)Î÷ðë‰÷Ù&.XñùÏaÅÅÅàˬ®¦:W_~¢Ñ$J ¡òd?˜Ô¶ü­›òâæ,~éu^ÒÓÓ¯x"iàSö}T¹ê•¢¾üĤôП¾9Ê\ó ƒŸíô¶Ž„ͺwr¬‘j¿Æ~?›üšOn^™W¯‰U/ä!„eô’§ç2P@ö?"GŒ¿ç‡ã©Œ©%¿×7ûý<5Çw¬É)·*ú¨ŒiwÏ©£òÐwúb¿ŸÒ˜»î¨~öÃ_þþ“wdÖïß\ì¤îàoÙO2'Ï»sÆðYÂSâ »G£ðàgÙO¶Ä¥Åš$!„³:·Â2*5X¢ðЇúð:ŸŠõÄÇûl,ˆø×ûýÔæ“›WæÕkbÕ 9Ba½äéùƒ Ôü(ûÉãïùáxJ ýF¦@öýd?Ù@öýd?ÙÈ~²€ì ûÈ~²|Qžê£ëÿðÊÇ¥Jü™ž\šãüžÊdY˜)ðoì÷À‡Õ<îÁ;ÇDé¨ û€¿ÒGŸ<,Æ@!@L|(\­¸¸Ø?ÄåϬËîã}fÞÔˆ kø£¦ý×Ù>þÐôÒeû«È~pýFšôtÿHƒnøíÇ9}ü¡OÝ”Eö?LšVºª´?4íž4²_o¡Žé`žÒ×l,kklu­ùWSò —d†HTýÀ¿RçÝ÷ ÊÇ|Ù@öýd?Ù@öýd? ûÈ~²€ì ûÈ~²€ìd?Ù@öýd?Ù@ö\¤ï“OñÔåîZµ·¤Y5 7ëî©!DN>­}1ÍñÖYyHÌ|ô+?øêmC+³×Ú4 À°ud¿^¤Ô:/™8Ï2ÿ±/1µ_³j۹ጴ°õëV …BhŽÒœÍeF‹šm)ÀÆnýÐeÞš}ÿضì1–Ï»§³4gÛ¦ü&ÐEŸ±xFŠÅœ<ïÎ1©!²á)q†B»GfŒî–1$ê†ÇÒ™ ²ðjšf †Ý®¡,4{ÉÖ=Ω7=¼šm)ÀÆnüo”à‹p_Ø¿þ\Â’Çyúñ…vm>ï”-qi±&Iá¬Î­°ŒJåVÑ=)£ fƒì©ÜóêßÞÍ6dMOà·¯î×PmËÛvXšvSfë Ø–ŒA`ìÈ~_ˆÒTRcÊ£B–™i©:×ôÉ~|Åzâã}¶‰·LŠ Â=/£!ñ¦'¿¾lŽzpm~«JºWÃÆú“;s,Óæ¥± ‚m)ÀÆn@pÌçué5š>ûFmËߺ)/nÎÒ±á\› GeÔÜuç‹¥Á#b B6dhpvE›2.”í`7j(yŠ ëÛ¬Ù¯¿!„âhn“ß^é\ºxB=lKÆ 0vƒì‡îÓE¤Å»²ÏÕOœ/Y OÛ&ETÛém ›uÿäX® ÖÓ2Féí{¶ìª±<05Yn,ÈoÆšÚÍÆOú¥)çÏÍÇÿ¹ÅxÏ=\+ lKÆ 0vƒì‡ž2 ¾ñŽôW½ù/¯"†ÏZ2ÄØ|rõʼzM¬z!G!,£—<=' t³Œf“4}aÚ–U¯¾æÖ™ã2g,ÉäTŸnך€m)ÀÆnàRR}sK'·4Ô§§§S&}¬¸¸8<:†­@oMŸ8|üÙÈ~²€ì ûÈ~²€ì ûÙ®ò]yñíµçµ0À€¥§_”Ò˜ýÏ÷w7_ñׄ%_¿{tP·ÞHk9ñï¿l¯û4•'ßÿõ;†™>{Tm=·Õ¶¼r[ð”eÞšÐw '›Ãã㢣‚tR ¶®·j×{ï¶Þüôƒ¬êüpèQZÎä¬ß}ª¤Å-ÇŸ1çÖÑ‘¡ZÏå¬Û™Wbõ#S§Î™sSjÐ%?31 û,]è¸w&¹U¥1oí®Ò ñ·,H’ä SwßÈ]{¾I—0éÎÉ1zIèƒãRM—ÎdzsËC¦åá‘ñÁ}Új†Ø¬¥fhãj®š ­Þ0Örþ9ô(¹®?á5óyÁuÇvlß²5*ñ¾Éê±÷×·›~ÿ­auGwìXýQÐãK&GÈŒGŒGÈ~0D$ŽÂk.5aŽIš" OmÞÎ÷^°©†ðÁfΞ3,L)ßúâ¿FŽ+Ë/mô† ±àîÉqŸÓÞ–âZ¯b;¼z0F¦N½%!ýó-¾=oõ‡ÙÍBˆ}¯ÿ}ŸN%núSËÆGz*Ö¼¾®(é¶oÞ5Äl-xûݺ>œi¹ìQÕzè½å[´¿ñ`V”N³æ¯{y«{î—îL.Ý»qQ•C Š6sÁ¬ñ®]/®lΚ`)8\:sNZÙ¡œÒVÅ>lê­·'¼úþ™Ôû¿;YÔæíÝØÎBÕ Í ./¬l•Â2g/\<>ê³µÊ]¾õŵiÆÒ³õޘѷMí>yÁ¡qÓý FF8+ìÜðl½M5%Œ™yï-Ã,•í¼›l»òiZó‰í[·å×;>ùœÈ¹_Z’V¶ïÊ%êø££dwuîž+ŸÅG5ä®x÷£!jÖýßLc–>ºx°á²°Þ^ƒJå[?«dØüjÇ?º¼b:á®>±{Ãþ3ÕÍ9dæm·L‹W|™‰¡µÙí<ðiÜ5Úu`Óçÿ\2)¢9¿½†øüs}|t°D×z®9ôè£n˜³ mLz´^$«§²‹kžÚ3µrÒ’[Æ ³H‘ŽÓÿØu¸°eÂÔHããã0Ð9üÁ3Ïvò°ËaŒŒ¤L]¡¶•Ê«5¦¿!Þè®Øóæº¢ É·/›—5ØYðqöYÝð‘Ižó *]ƒ¦?p×ÃÔ¢ìœÃðÑ)ŸŒ’>4**uTÖãRL•'ömˆ3,Ö( !„dˆžê9UP9háw¿4÷†òCyMqã2#ën:Ùèjó¦ŒË0—íûø\èì9câ—oc%c¸±úðñ ÃðÑiæÖã[÷•ÄLŸ•·|ã…´…÷=4oÜ ¦Ãkº3RÝy§*Ê]‰7ÍÊJn8´ýLèÂÇ—.¥UÊkŒ••Þº¯ƒ…ªVÓf-»sJ²5o÷±¦Äñã?lkñ‚ÃÈù.Èpß»ëŒaú÷.Hl°dŒáÜÉ !³îš£;üÏ«—ètG=fHËž7Úyþå5f̨$[þéúÔ;¾ûèìÑáWe¤X‹¯nÐ$Ïùù+9a¤áôÊMg®¨X|Þ76œ š¸èáÛ& ÓÇÆUg_þeўܭ§C>m‚pqzóê‚ÏþÚ| ý†øôs³†Ä†üPÛÔÔd¶XØ:×uè‘M‰ ‘YÍV”½¿À“qëôÁmGsN)éÓ'¥„ÊB’½rOWÈiSG„ër<üiúÄ~¿ëÁ[_TÒ¦|{Öà“ˆž8.áøîS¥¶I±Bˆ äƒ#ÍúБCÃ+®wßmþtP4ŧB;³ìØç ½£‚ —œ²,Ëai#‰½§ªZ#Î]Л˜Qžw²¦U+¬“ÍJµ\½…•BÒni^w2¿qÚ˜’£u¦Ì{í…{ìÂujûš³’зNjiSd!LcçΘ–¤·Ï™No߸«aÌÈI£MRÝ5Êœ”‘¤Ó§„‰B[‹KæK¯!dŠKŽ õ¦„‹#†¤!‘AáúAá¢¤ÅæÕ¥Œºë΋¿“ŽˆÝYÞÜìRÛ{7]Ä•OÓ‚%!I:^/é$Écn.,mw‰:øhg]y»Ï¿jA‚%I!I²,u0v]Ù S,âÓJJ¶ï¾ªb-©ÍevÝà;&¦D›DtX„žò}W|™V5"Ú¤~ÖAë¥ÿÔ7dwÔ?×@zº:ô\¤9г7¬­ˆ›wÿ)FõtW>ñˆñˆñ€È~ýDñ¨B’åŽt{…ÁÒÁOerHÊØ¸Ý» ÖHé‹FÔòÖå*Ujâ¬Á!í¾Â”0eTHÞé“yÊ…Æ‹“LÚ9YèSîzlѰOGwùV!d, !gÜúeçŽç>¶}ý¡ÂÙOÎèòBIB¡uöàå‹i«8¼ÿD^Y]‹Óí"VkÿÝT[š˞&Y†L¶jóÛ¯í0†&Mœ7?Ùdm‰:ühYßÙó;_.4èÅJv±ÒÕ_FuhôçMðÔ}—¶ÈŒ%ѽwgŸ í=Š5ëÚµ¥Ñ ¼uB´^%<.DTÖ7¹µAzIs6Õ9EX|ˆŽñˆñˆñø¸ÇÃuIÔ±#†„({•×5×>œ[-¢G¥†ÈBá¬>_U×T}âà™V)atüçëò6œøà½-Ù…*J >ÞQì‰Ì2( IDATÓA2—C†Šv9¥’4z÷ìÑ"Wìøö~e½ø}âljµn?Ñ3~t¼^;"=Ô[ºmoхƦòS7¬¼ô‚ٞƲwܤ›çÌjPm6·vÍ…º’»öÄšuûN·©VÉunë†KÂæÜÿÈÓ÷OŽíði¦¶^(iÖ„¢¸Í§m9ÚÖé]ÅÓÕçËzYxZêšÞöߪÃí bá±ÃR,JÅîC%µÍ çŽ>V£^ÝÖ†K› ­í²ºÂ†uµ!0ôt>ôwýÁµ+VÆNjª?Ÿ_XRéâÆŒŠU/lÝž{¦üüþm*¥øIødlð´;ož-+v!„°ŸÏ~#Çê Š›¸hϷ’1rPHááÖîÖ ‘©7,½urÇ×͖ÆŒˆÛ¹¯uHæ £0&f¦éKŠb2Ó;>›ZŽ65)g}eüÔ‘á:!tIÓš¯®ß»ýÍ\M?fêK^©ÚjJfoZm×ôaÉ3çÑå\s¡.§¹›«Îo:%½Óu/>shÔÖ¼Þ.‹<8&L×ÐÕ§) gÏ5ÇN~tQF×V~dëG{Žýúm/Q» 4­KÏ×GŽŸ˜»gß›ï•Ýzÿ¢)QíL~®hP¥¥óÕ@§‹šñÀÍÞ 9›^=$‚2o,ã¯ø2©Žš’ƒ»?k‚Ñ–úC[.i‘Äd]×COçCR{hóÖ—®»¶B1hî£_—õÀ®µ»r>8£ÂSf,™31Bf²h‘û òìš·Þ·Þðø½Y rkáÎ5««F=ùØ”8 êWŠ‹‹Ã£cØ:l©he½5}bág¼v~ø¯ÖOŽnÑGÏ~ðžéÑ~vü…qÈÍ·LÙzàWy„>|ðÈ%wO¸þm;…ÄêŒGŒGöûðEì÷èÝégä€ÿ#ûÙ@öýd?Ù@öýd?úk>£¡ÅJ™Mtx˜O}VB°b`¼€ëžý|m³ˆÀxXMKC=kÆ;èÅéÇ|€ÿ#ûÙ@ö:¢9K6¿þ¯ýu^J`°€~§§¸>cañªŸ}ç¯GâãŠýñû7DZ¦ì ?±ß×s,BÔmûÕw~·³–D v@öƒ¿Ž…1"ì€ì¿ £æ<ó÷?5Ë̈`°²üi,<¿ú³±0ú–¾øƒ¹C2ï{þ_»tDälxƒý0 )-§sòB3÷‡úï9ñz!„4ôÞçÿôµ¬ !„¨;v¸Ô¡Q)ƒô9Ýžy¶“‡]{dd$e (—Ëb6õ䇄Œé“-•Õ‰=ÿí›ã?¿Ö™dˆ9kjDuŨ?ÿÖMѺ>üJ¸šššÌ ['¾6Þ]¿ÁŽñÀõž>IõÍ-<ÜÒPŸžžNJC‹5:<Œ¯„þU\\ÃÖ ãôÖô‰c>Àÿ‘ý€ì‡À#I’ªùÐ9ꪪI’D»ï€ì‡ÞdÐë\n·ï|—ÇmÐëiãýЛ,f³Óåv¸\ªÚÏ¿†ªªæp¹œ.7=0ÞÀÄÏK¸’N–ÃC‚mN—ÃÕ¦õëÁ0’$ôú°`ÌÆ; û¡·É²j ¢Æ;ðŸ%²`À»ö1ŸÅÅÅ” €bëÐuR}s UÿÆ1Ÿ@öýd?Ù@öýd?Ù¾ó‡[ê©Ðë£cèw€Oõ;=û !ÒÓÓ=×ëÕ4z=&I’^¯7 ÅÅÅô;Àûžý<Çã¡RÀ¤iZ×»ýèû~€»öù~^¯—2½¥‹Š~ô}¿ г‡œ½¨‹Š~ô}¿ г€ì ûÈ~²€ì ûÈ~Xšâå–_ý€@¡ïå÷Sw¿÷Þîæ‹ÿ0D$fÜ8󦬃4à¦'ö·Þ>6òû§Fôis\PÑé õmJÔ¨[–ÎH ¶â£»·/®sé"Ò¦Ý3|œB(Mg³ß:~ê‚]?jö=³†E\òeœí,¬æ¨<ºnû‘³-ZhâçÒt:ýë^,LÚúê+Ú“ß~Xüiyá{g˜;|…Úzöø9¯•÷Æ3Ï·<œ”óúÖ BaÍ?^隯÷ÕÃÛYU¤Ïª½µQ¾ú%RéŽ+º[ÄJúd¿+xí5'önŠ›0&\§9ÎmXØ;ýÞo ÷^ØÿÏ­ÙƒœŸ.„j¯­ ½ïñÇC›üû•ÛGÞzï7éÊv½·bwIæ]AÎÒë:&Þõ¥±ró©5«6¬µVÔX±ú«u§ÐÔ,ã±½MªØ÷Êߥoüä¾™‘™ÔñDR7ÿ™çªü“•%ªp¬|½à⟃²žøõSYÁ>;í`U¹dn}ÕÚ¸ ¼¬®tyw¬ä ß0`]c>Õº½ËûÒËÿûÆšãÆÉÝ1.J''‹#g0)(qìäàÊÜzBèǧE„>")Á$EN¶È’iPZ¤h©oS„óBî9ýÈ[ÆÄ™eÉ5bö(sÉÉrûå¿øwøÎI:ÍÙPZÕâÑ…NŒ0 aŒ71´æ@‘Už ¹…ʰ¬TS;OûL»ßÁ©3è…ª^œªjBo4]ú+tÇ 9vÔ ‹,äàACC]UMnÉ’:ë¦ñC ú ¸‘)æ–êV¯B3erF´Q6F›ža¨:[çîô]Uyźa7‰7˲9fÈN˺Öô¬K!„11=£ó èÅu(tÌc¿|þ®A—üb2òËÿóì)¾|¥‘kô‹vÖF—ýš/½³’+­ä+9ýnàö;|Üu¹ÖKìŒe_íØýáš\i”„P]6§§íìú•d!„Ð<CÂmI²,IŸŒé’$4UÓTg«]5§}2Í“-A¢ØêT/Ë™¿³)yÖÒ){·og3vúÜ££ºðqâ÷̯ÍH8XbžpOŒAqÕÓ>½˜@ûßÁ‘ukÊû+?|7Û ™cF-ž`èòWúd %¡)š&ûœöëŸÝ;ÌG§¡í¯*𽓗Ht%¥ëïßÞJ®vs%—XÉéw¶ßàë®ãm¾ QãßyvûŽüVÕ”86ÃybWa£[ª»ùÜ©3UîkÏãÌIãÒ=§wntkÂÝ|fw¾3uÜ`‹$tÂÑÜê°55ºµÎßÙÛRzªÒæ†àP‹Ao ÒKBɘ0u¤±¤Ð:d‹'Ž´û´N¾C°12ÑT¹áí¿ýú¥—ý×ümý‘ŠK>´Ë «¶Õ6I±Ãb̲»¹´Æ®~ú¥‹Šëªê¬>¹«D>*ÖÐé;›âÒcìEG+ªP¬e¹yÍ\ïr®¢ G’¿ûâ ߸1¾ÛP!¼U¿þÉ4hÜWþðês‹S$!„pŸZþÖáVŸ #ÝïqR/¹¬»õ`%oíÞJ.±’Óïn¿ÀÇ]×ë|ê¢ÇÎ_öáæmIwŽ^xÇÄMÛWÿ~»S2†'œrÛ°kO¤ ´ÛiÇš?d;…1røÄÛgËBKÊÊ´l\ÿâùè‰ ÏOIíø5ÅÑ|:{ûÆVU2FŽš5ïÓkÀè#“ãƒÏOI4J=ÍÞÉw²|\·ð;ËÒ,’PlåÛþ½)ûÂØ‡†|rž dNíÚÂêbÇNHÞ°í#Ã#ÓÇYš.N~£ã¬{ÿþje›1bÊ¢[“ŒÒ§WBo÷uá#IfÅGoüN‘4lü ‰æ"Öë+òGsÎÿü(ù·?Z6y×˶{~Ùõ ¨BŸxû÷=ò÷Ï|â·ÏÞ‘j–Ò~õ¼øñÏÖX§ëéia>»÷¡Ë+á5_b¸¼»}r²U—ß_ÇJN¿ ˜~€“ê›[:y¸¥¡>!!ÁßZ³ç¯?'ùžÇ?¿+C·xkö½ÿ^Ë”Çn©×ܧV¯Í¼øÞéÜûÚ79ŽüêÉ_u!\öÓÝÓƒÓ…‡Ík 6}º—\ó:ìª9ØØÓhuuuxtLÀõ;Ðï|»ß@öóÃ9¨Ò|ô•UÓ\4ÊÒÃI„æª:°cWNY«WH†Ä¬é³nJãʃ û¸ß@öc ý²žL €ì ûÈ~²€ì ûÈ~²ýd?Ù@öôý5ŸQ]]M™€>F¿@_g¿ôôtÊô¢ââbúàƒýÿÆ1Ÿ@ö 4ÝjµyT*Ðï°ô” f(Bó¨^UÓ4¡©š&KÒÅÿ—„$K’AÖKB¢J¾ÍS±öþ“þÔOjºäÏŠõÜž¶*mBœ2ñæ…·Ï®£býOÑT¯ê½øš²$©šª“d!$Y’27ú ûõ”ªi.Õ- a” ÅÕè²V;›\Öfwk«×ÞæqhBÓ4Í®8-:³$I’B A¡zK„14Ò–`ŽŠ2…éL.Õ#„0ÉFY"^«æ-9/>ÿAëìï>s×`C_g‹¦Coÿὓ6!„ˆ‘©?sº¶ìȆW Î/ýÎãÓbè:}˜ñ\Š['ÉYoõØë]ÍuΦ&wk³»µÍã°+N!„WUܪǢ7 ! ’>Ø`ÕGšBcL±æˆHc˜AÖ»·,Éf‘’Òï û¡.Å­ ! ©ÄVUd--n­,·ÕT;¼šÒÊKº„ è”à„!¡‰#ÂRÒBM‘…lÒ¨¶OÍ~›¾óÁÅ ¨ˆ»í‰ÿ˜V¾ùï/o-S+–ïËxzV ;!®MhNÅ­“tnÅ}¶µ¢ÐZVf«.³ÕÔ;›5¡õì=Í:ã`K\jHBzHÒˆðÔ„ hâ5Èz½L3Òï ûòìCS]ªG'ɧZJÕZË*lµ=žt^Á«)öÚ {í¾º\!„$¤ÁÁq#ÂR¦ÄŒÎ OõªªIgÐIœ‡ÙI2p”íþ÷‡[ŽU:äð!Ó?|׸àÚ¾óѱJÛÅ&Ò|âù‡ƒ^öœuo?ÿjݘñÆÓÇÊlæÁ3–ýÇ’1a²f/þøw·žj”£“#Z/û¥îpvñ§'ÕnY¾yè×.øêSÒß_ÞR¦”í>X3}Q"½§WyT¯¢©nÕs¬±èxcQ¡µ´Ñeí­7w*î³­g[+¶‰ÃBƒ¬’82RðæïW®Ù3-saTñê77_ô'ÇŠ“¼Z~é,ÔÓXÚ Äà{ŸýÆÄPI!ÉI’Óæí)ïÿ¼½¾´Ñ#˜ƒöVäÓ„Öè²î¨>r¨áT¥½®o>´ÈZVd-[SžmÖÇF Ÿ•5\ÑT³ŽH¿€ì翜ŠK’ä}µ'vT9c­è­]|=Ÿ§ZJNµ”¼unÃð°”9 nŒ§ig(]:7¬>Qhׇ>øóqI¨EÙè$Ièô½A¯“¥„XSÝ®+žÓ`W„aCG§EkCÒž›âõœû=]ªgWÍÑ]5G3ÃÓîK3<,E/éð@PW}ñé«NÉ5(ktؾk¶Œ}pZœýÌ¡S†i RÎkÔ4áqZ«‹ö¯ÿ(bÙ‚®|Î܈vVþ¨ŒD]Náþ‚ÚØä†gZ.{P·ðÆM/ïkBˆˆáãRõ•;_ûËús!DÈä…7Dp4n÷¹U¯&´=5Ç×”ï®u6úì÷lr·®,Û¹¦<{j̘¥i·DÃsß;ý²ß€O}^M9ÑtöÝâÍ•ŽúòµO·”ü2÷DKì#é·‰H×Kú€º?„#Í›ùB!‚§ýçï|ò>ïû½ý‡]š1fÄŒ;¥ºã'[RnÿÏe£M®Æ‚õÿܸqÿ´Üqùs íK {ï}ß\ó¯ßžŒ1uD¢®é²GÍéw>¹¤ñ¥Õ§¢yÏËÏçG!Ì·?¹d¸…=°Ýrñ¤¾Í•9«ËvÙ¼ŽñMÝW—»¯.w\dÆcCŘ"-Òïð3R}sK'·4Ô§§§ûÍÒºw‘µüŸÅËm5w)R‚ãz{Fè`ç !„#ïϽe›ÿ­'f&hÕÞþëFÝÒgŸ¼!¬w&‰ª£2wOöÁüÒ:›°D'œ2sfVrðÜ÷P\\ ýNÕT¯¦î¬>²¢t»Õc¸ 21:óËw„ê-ô;íwýüdêTÜVíoE+ šÏûGËöä°Å!z W‚ñÔ]ûÞúœó-Š0ǹùî¥s‡…øô‘a“ý\Š»ÐZöúÙuÕŽ?X$ß:hÊCnÕI:®ãý²ß€Ÿƒ*šêU•÷K¶n®<Ð÷lèã™è¢¤é÷¥ÍÕK:n 8€Bös«‡×õ—Â'›ÎúYóëÍ_θsrÌ(“l`eö§~€ßó󟮊û|[åK…+êÍþ·tЦ®«Ø“SŸÿÍÌ¥©Á ì„ï¿ÕG—ŸßìRÜþ·t6¯ó/§?1äéKC AF  üv¿ŸªiÕóVñÆíU‡¡!ç'N}8ý6C€]f€òãý~Õk÷:_(xÇ—/ŸÛ[Œ²áËwLgÒÿü¡ßà÷üs¿ŸKñÔ»šþ/¹œeÔ[*sòšÎ}ô#ÑæpEC?õ;÷±Æ¢WŠV9W ,¯[õ¼R´ê`}Áf.5éŒw |œNV\Š{_]î޼8Áï¢JGýÿ;ú—œº|—âaÍF_Ò„æRUMu(®ßœ|ëlkE€7êöêÃåöšgÇÕRúû‚wØÏ|ÑÖªƒµ®¦ï\fÔ$!Ñï€Oñ‡ë|zTo•£á¹ÿ°y´è¥BôA?Ïz2Þe°÷¡Ö¼¥Ë½º¾†tß„'ï 1~> õV}ô›_¬®¸ìX_)rÖ?ÿðP»ù…\çÓ¥¸÷×ç½R¸J}íRi!ƒ~:þ‰ Ù( Ø‹îv£ß !\gÞ|öwûm²NwñϦá?÷í©a¾¶ð\瀿ßÏ­zËmÕ¿Ì}#Ю0Ñm^ÇO޽ò“ñ_l‰7ÌøW^±r}û‰¾jEÑÁ7Ü4è³ ¦~П¼¼P­õàÿ=»aìO~²0^Ï:pý‚ߎš£oÝ@ð»ZI[ÕOŽýí¹ñOZôAôž+ÝèwÉÁ“¾û›'39&Ÿ6°Oó¨Þ’¶ÊçO¼FðëˆCq=wüe¶*êˆßwMÇkm;’ãThâ~ ~[ª¾yv=Á¯#ìu?:þ7›×¡iýýz!øUØk•û—V¿ÆL]õüâÄë•ö:¯:ðfl¥îN´–¹˜ƒöCðÛYslyñ&JѹGãOÿÝ¡¸bBîv¿Sm‡ÿô_O?ýôÓO?ý½ÿÝVK¿À' ÔƒâM­q6þ"÷u‚_ãßs¹¯ý2ëkqAQëÒ/!²Î# !:®:ѧœŠû`}þ›g×SŠ®¨rÔÿüÄ«Ïe}5H7À†ìv¿“ƒ'}›c>ður¿Ÿ¦iVíù¯Ù½Nš°‹ì^çÏOü£ÍcX¡Më8©êR'qF_ßñ¨Þ³­å+ââ.ÝPf«ù]þòwTúd?_áTÝÏøG€ßO¬¬Û¯O¾9°ö”NH›‘ÐÁCiÉsGëÙï×G¼šRãhü¿¼©šJ5º%¿¹øÕ3kÜô;@öë.·êù]þòjG×e¶š Ò^Sè-Ï uÕßãâøïä8-ÚW^×ó¹¯qˆuÏì®9¾¡b¯KqÓï@?`÷÷s)î¥Û×Uì¡å¾ˆ%)³ïNžmÒÈ÷ÕœŽ¢må´Ô6ªÆhKÚ‰ÓçDF ÜS‹Üýýܪ痹¯YËé;=ßÔ é'ã¿2<4Y?`î¶pý¿7NÛp«Þ¼æb‚ß·¦,;3,utDú¹ç»dq{ƈÛi¹þàTÜïžßBðû¢AJh/ä/aÒ·Ã!’èw ï ¤c>í^ç_NH›õÊ4ôO§Þ·+\)×àQ½-ç7W _œÍëüßü¹/¥d¿Î¸UÏïòÿÅ=Ü{‹Cqý>ÿ]NßB眊û¥Ó+¨Co)n½°¦|×:ñýúšKqo¨Ø{¶µ‚ëE…ÖÒMö3 EGܪç§Þ³y”¢EÜoÖjIDAT­.Ͼ`¯ãr©€ì×Mh-ÛŠÒ´V¯[Qº½Õkçvm¸šGõî¯;™ß\L)z—ª©/žþÀ«)”ýÚ™ƒ¾xê}…©Òõªín•p%—êyëÜFêp=T;V—qä' û]Nv×çhÏë§ÈZ¶¿î¤‡ø‡KƒŸâ~¥h•ÝËÕ€®—5åÙ-ud¿Ïy5åó›i§ëjyñ&…³ð)MÓÊíµ‡ê (Åõ£hê+E«\ [d?!„NÅýþù­6v>\g­û%s.òhÞ¿­¢×[~sq¡µ”Ÿ]ÙO!l^ÇÖªƒ4RØ\yÀÎý3 „¢)ë Êl5”¢¼vv-g2²Ÿp*®q,bßÍøÕwŠ7;ÙõÇš ©ïßJúF£1§>Ÿø=ûY=¶uy´PŸÙS{¢;¹6¯¦ì©9Qïj¦}æý’ù… tös*îwÏoå¾s}IÚ;Å›ùÀTMû°tuèKõÎæœº|âèìw°>Ÿæéc9õy•ÃÏ6ø©GN7¹[)E[Y¶“Ã>@€f?§â^[žÍá}OÑÔ5åÙ.•ëÎ"¯¦¬.ßEú^•£¾ÐZÆa ³Ÿ,IÛ«Ó6ýâ㪃UHå¶š’¶*êÐ/V—íâ&+ ಟª©ûêNrÁÉþâTÜ9uù*;]ŒCq­¯ØKúKAóy§Ú€@Ë~Õ»ù¦mªÜïV½Ô! HB:T_@ú‹&´M¸9ÜTökr·žo«¤aúÑ¹Ö ­;uª¦f×ór¹‘~µ£úˆ$8àLöó¨ÞÕGh_˜†zØõ0ܪ7»æuè_V­ÔVM@ d?MhûêNÒ*ýn_].W ¤ìç9×z:ô»mU‡8ÕJö«w¶Ô9›h•~WíhhrqŸ·€ jêžÚD}_p¨¾@'ÉÔøöójÊ~vúùŒýõ'¹Åb p©®òâ#Ú¼Ž*G=uþŸý<ª÷Xc!Mâ#Ž6rÕÁ@ “ä"k9uðûëò¼*Ýþžý$!qÒ‘ï8ÛZ!sÕÁPØRªp…OŸq¼±È£q™%àïÙŒ“Ž|‡ª©g[+¨ƒs«Þ#§©ƒï(i«â”?àçÙÏ£zO4¥=|ʉÆ3?ókЦµ”Qß¡ í|+78~ý¼šrº¥„öð)§­¥NùókzIÇ=å|Íñ¦3^ŽÂ~œýŒ²¡¤­Šöð)çÛ*M:#uðc•öz®æêkÎXËÝ ¿¹ÿÍ~Mn+?uûêmvs—?v®•+|úœ2[µAÖSà·Ù¯´Ï|tJü•SqŸár>¾Çê±yø! øköójJ‘• Nø¢"k9Çú+US+ìµÔÁUÙ¹Ã;ðÓìçV½ÕŽÃÕ8¹Ã»¿2ÈúG#uðAöŠü3û M«s6Ñ>¨ÖÙ¨iÜtÑoY=6Šàƒ.Øëû~™ý ²¾ÎÕLcødökâ²þªÅÓF|S³Ù­z©ðÃì§“äVÆðAVM'ÉÔÁ/qWŸÕàja;ðÏìçPÜ´„Ïrª´ŽjqsÀ§jóØ%I¢À³ŸÝë %|–Ýë¤~©Ém¥¾©Õk×K:êü0ûµ‘ý|˜ìç·Ùc>}T›ÇÁy¶À?³W5ðe.ŽÈõG^Mñª\IÒGiB㾚À?³ŸÊ,LJ1õ×xÁéw€ì×לìYòaì÷óKªP½ÜAΗˆìü2ûÁ—q¥yšýÑ@4ðÇìgäª>Ì$(‚ÿÑ YÜEÀ‡ˆë|¿Ì~z™YŽÏAevû!MhA:uðYärà§Ù_¸}˜‘ý~þÈ ë¹{¸7E~˜ý‚õA´„ϲèÍÁ/EC)‚o Ò™®Äü2û‘.|Y0­ã§"É~¾*Ììá®§€ì‡>fæ¬0?n¦¾)D¤j\çøcö“„dÒi ¤3qN˜¿â˜Ošýúš[õÄš"h kŽts왟â˜Oîw\ëøgöÓ4->(ŠÆðAqæHcÏü”^Öq›ß”Köþ™ý ²>ÖIcøfö3p?åV½±fö·û¢Á–8Šü6û M¢1|PFØ`ƒÌÝýVrpEðAI–XŠü3û !ÒCÈ~¾(-$‘"ø+³l2ˆ:ø“Îbà–§À³_œ9R\QÒ·HBŠ3q,®ÿ¶¯$ M¦¾&ÙçR<ÔømöS45ÑC{ø”$K¬WS¨ƒK á˜OŸ“š¤ç@kàÇÙO1<,…öð)™á©ìŠõ÷þ/'ESŸ2>j˜‘ ,?Î~fq\díáSÆE3éŒÔÁiBÁo.>fD(-ü:û !F…¡=|Jfx*EðoüæâkbÌF;ý€¿g¿ÿßÞÅÆuÝw?ËÝf#9 9\‡wR”HJ¤Dí¢(ÉZ,ÉZlI‰ã¸–J‘ë­qจãÊMÑ%qR @€ö¡H¸pP If'n'UlDnTÚR$Y;E-\gæöaÇŽd­$g8÷ûyåïüÿ<ÄùÍ9÷ŸasÃ{î(÷Ûl<ó€öH#EÈ‘F×u©Èóìç Ñfš+:ÂR*ê÷ ©8uÈ cml´ùŸýle.*žCKrÄ¢’6KÔ!ïi©:"MÔ!˜ÊàõKà‰ì'„¨ U ‡®d]Èô׸õÛ+yce|uÈíá†dš[U€7²_ÊMuÇZéJÖuG[Snš:xDÌ),qÂÔ!ëV–Îs 6|od?GÛ«J»èJÖõ•u9¼täRÈÅÅs©CvÙÊœ®—‚;5€7²Ÿ¢&X± hLÅœ¢ª@)uðSkË’:²«;Æb;ðXö“Bô•vÓ˜,ê+í&xß°›¸Î1«6V.ñi›:e?– ²½åš²n“>=ÆVÖúŠEÔ![Ê|± 1uÞÊ~BCéùÑfz“ b­Áσ™_Êy‘¦"+D)²âÞÊ%Šë4€³ŸOÛÔôÑ›¬ØQ½ŠS^¼É‚¥¿¬™þeñCjJ<—ý„q'ÒPPE{¦Ysa5gý{–¥Œ{ÊÚʤÓìžòм›ýLeîªYC{¦Ù®šµ–fêï]RȵäiåÓöÆÊ%‘x6û))ëCUõ¡J:4m ³‚eœ²ãe¶¶¶&V²éw:m¨\¬yÓx9û !,m|¢nš6Ÿ¬ÛÀ¢´T*–P‡éá7œM•ËXô^Ï~RÈš@éÜp=M𑯠 ‹~°•¹¹jY Óàþê>%tÀóÙOakëцûØ5Õ´Ô{¶°Ó¿û{PÖ®§S­Ôí+ëbÑýþ_Èô¯-_HŸ¦Ô†ŠÅAÃGa*£§xvM°ŒRL©=õ›5÷:²ßûmí¬YæÊé)± vT¯²YôÃãŸ44íà¶ñ©Ómi,¨bS û}xªôþ¦í´jŠhÚa(& ø)e±^WÎUïS§í}MÛøÂýþ–º© Ñk£[“nqñÜúP%Ïp-G[;kV—8aJ1é®ßÈk~€ìw}¶¶ú›¶±ósREíÂG·°ø€b*ýtëÇØù9¹æEšzbs,eP @ö»>KÒú1.!˜´ÆKõtënpã?’2_t{¢—RL–"+øXóý6i²ß h©«ñû+è٤؞è­ô—pÔnÌÖÖ¦ª¥Í…Õ”bR²ôS-» ~€ìws޶¶&V´ÕѶ»Ôn¸·j)»=q+,e~föƒì¸¾{»jÖÔËx½ýnuúôìÝQ»Îݱb'üdë.›Ýž¸e޶žm{È ´Ü…®h˺оpd¿Û™†*ëùö=~áywÀo8ŸŸûÁ·ÅºÌÝ×´RÜ™D ~ y¯×²ßm>±Ta+ôÌì9~ðfðŸkûdØ* t¸]¶²º¢-œûr"vÁós÷8¬ø²ß°”Y,ß߸c?oò±æû¸©Ø¹‡;áhkKbùŠx'¥¸u~ÃùBû^¿áðÏ ýî­­±ÙT/-¼E{6wFyÝwÃRæž†Í c³)Å-ý›Ræ í{£¬´²ß]Ç?sE¼s÷¬µtñ¦>^»nYI;Á“ÿ4ïèˆ4RŠ›êóí{Ê|1ƒkÜÙo2⟵®¼çµëiäG‘B>T·amÙ‚&1Õ<Õº»+ÚB)>Š£­çÛIâ&Áý&1þ­.ë~´a ¯Ó\7øõ7mí+í"øa’Ç2oy`Iñ\Jq­€áì诔q°'È)ùð´­­¥%í!3ðÕÃߘH'ij†©Œ'[vµÕü0,eö7m-²BÿvâÇTã}1»èùö=a+ÄŠÈ5yr­­öHßµ?4|4U2ý/vôÏ ×ü0¥ñïš¾½ ›9Ë$cV°ü/çˆÚ…?@ö›Êø§Ìª@ü¯æ?Vá/öxS«ñ¿žÿÇ•¶œaÊǶ–•t<7çá€áx¼=±¶Ú÷ G“„Ùoª™ÊˆXÑùéžX›g;º¤¤ýÏ;ú‹¬ !¹ÇÓÿš _êz<ˆ{³Zª‡ë6îoÞnk‹ÙošH)mmîoÚ¾§a³×¶]™Êèo¼ïS [˜€búÿöŠ¬Ð‹ûzKç{í³G삃ý½¥óm–Ù@nËÏtdksy¼sn¸þoÞüúñá3^hd"föƒ…V}žÈ )¤­Í‡ë6.ˆµþíá—¯&G¼ð©ÆÚö5mµ”É>Oûòv¾b+³Ä±sÿ–ªåù=-ÓRmKô¾Ø±/æüåq§­¶¢º—ºŸšiÊïO2ýOµîþtÓ6Ÿ¶ ~`FÈç]‘™ýŸÛ+W–Îûʯ¿ñΕ“ù÷kCO4ï,²‚¶&õ!'˜Ê0•ñDËÎ7/|í7ß¿’ŸqiIû#õ›2Ÿ”Ž€“Î]ºÁ‡ÎŸ«­­éÒîD:ùÚ™CÿôΫ—'†ó£s!ÓÿñÚu‹‹ç˜Êàí¾™e`` 0Ëûq—tS©têåcßÿöñ×’n*?z—Äû·Uú‹¹=%ÿÆyÏ_ZK!-e.)éè)žó/G¿÷í?™Ñ3QSë+mKôj©Xv@îþs‘ÚÐz{¢w]yÏßÿæ_߸ðöŒþ8…VpwÍšE%sMi(É·-€ì—Ó‘I›Bo¯^µ¹jù?¿ûß?õFj¦%@CêÞÒù;kV›Ê`Ù3‚£-G[·ì<;zñ¾õ«Á#3î#„LÿÖª•«Ë»¥|Ûf.Oìù¼Öhj|<=ñʱ~ïÔÏÆRã¹ÿÀ>m¯*뺯j¹©L‡Ô7ÃydÏçuÇÝ™ÑÁ—~÷¿ÎýÚnî?pÔ.ÜT¹´·¬K‘ú<0î ûåç4c,5î ñ÷þóßOüôÜØÅÜ|Èb'|OùÂÕe ¤¬õ‘ýò"Ž 'Ç^9öƒŸ=4œÍ͇l(¨ÚT¹¬3Ò(¥4¤æ–ìÙ/L¤“®ï^9ù­¯ýüüá‰t2žÊTÆühóÆŠ%ÕÁ2%„ÁšÙ/ßฒòçç¿zòõ·‡ŽæÈ2`Èô/+éX_±(d,e(.o ûGH"³•«± Qˆ+©~yáížúÅ¡Á#Y9ÆTÆœ¢º•¥ó:")7íÓ6 B^Êl]uDSnêG§ýèÌ/ÿ÷ò‰¬„À á뎵ö–Ο,O‹´­X`d¿¼– Z b³ç5˜JÿÏ¥c?=ûæ›Þ97Õ¿ºÜ›®_TÜVªœpS޶¸¶^ ¥ÌŒ»µå V”vº®{hðÈëçÞzëâÀ¥‰«Sú«µT³‚å‘ƞⶸI¹iÞ¤d?MF…ô¶bvQm}¨J7%ÜKÇÿ{ðÈ;WN»zjR¦¤f :XZ(oÔׇ*¥BÈÌýìM÷(©2!°§¸­=Ò`JãrrøíKG5xäØÕÓ¿½zzô®Ïd’B;áD ^ªìˆ4TúK’nÊTFæu>“²Ÿ—e˜¢-\×TX3žž°”‘tSgFO\øíÕÓgF/\ž¾’¾<1r59’rÓi7=’ói[I¥¥ ¾é þéû"•þxÜ)q†Ô餩LSqŒð!™¶B=±¶ÎpSÊMÙÚº’>;zñäðÙãÃg/Œ ]N_ž¾212œq…H¦“ãé¤ßp„–2†/húC¦¿È ÆH¥¿$î‹Äì¢Ìu´•y‘Ïä ûáZ¦Ò™œf £:PZ(펵Œ§&RnZ!¥ÔRI!¥†ÒÉtÊ®+Ü”›v]W¡¥²´ùÁœÜ”­ÍÌš\¡,4ƒõ¡Ê”›OO¤]W ¡¤4¤v…È|Õ’9¨)íºi‘v]WHiHe©ß/鱸È~¸RȺtÁ`5˜úw»C¯Å÷)7À æ@öÌ|7ß"u~èešRÑ‚œz:Nwtx1ûåÚ ‰)¾§Åyfèü9ZÀ¸£é98îÈoìù²€ì ûa:¸£ï¾ú_ÿÉÙ$¥w×ÅUÈy0xå OþÝ#â;ÇÿôËŸYYBOÆÀbÝ/_& Bˆ³ßýâ“_úÁV!ÆÙ/_' LCÆÙ/o' ‘Þg¿öÕOu8LCÆÙ/Ÿ& ï|óý htÕs_ùl߬æ¿ÜÿÁi(GPŒ;²ßŒ–:üú[#Bë{î¥gzã†Búê¶|©¿Ã'„gñ³£#.•wB!ôgŸýÜ ~<62‡)ÓÔó;ömGö`ýânÿÉSå|beü÷ J3ܲ|aÑ©÷b»^x|iTOã#áÖ :~?ãŽqǸ˩q@Þ“ç.ÝàÇCçÏÕÖÖR¦©s~èR´°€Gò”ÂhŒqÇ9ã.§Æy=Ÿ@öýp—¤”i7‡Î†H§])%}ãŽqÈ~˜L¦¡ÇÆÇsçyÆ&ÆMà/`Ü1îÙ“Éï8£cã#ccét–W!ÒiwdlltlœÃÁ¸cÜ€üÃ7ÍY¦•* ®ŽŽŒ]q³º MJiFA0 ß€qǸd?L6¥TÈï£ã` ç?”È~€ïæ{>(0Íw˜\òÜÅ!ªù=Ÿ@öýd?Ù@öýd?ÙÈ~²€ì ûÈ~²€ì ûÙ@öýd?Ù@öýd? ûÈ~²€ì ûÈ~€[õ¢~ZO¦¯bIEND®B`‚python-hpilo-3.6/docs/networksettings.rst0000644000175000017500000000065712652734620021551 0ustar dennisdennis00000000000000Network settings ================ By default, iLO interfaces will try to use DHCP for network configuration. With these functions you can inspect the network configuration and, if DHCP doesn't quite do the right thing for you, make manual adjustments. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_network_settings .. ilo_output:: get_network_settings .. automethod:: mod_network_settings python-hpilo-3.6/docs/contributing.rst0000644000175000017500000000304012652734620020773 0ustar dennisdennis00000000000000Contributing guide ================== python-hpilo is maintained by Dennis Kaarsemaker on GitHub_. If you have a problem with the software, that's the place to file an issue. And if you want to contribute to the project, that's the place to go to as well. Patches can be submitted as pull requests on github or mailed to dennis@kaarsemaker.net. If you are looking for a really simple way of contributing, please contribute test data from a server model that's not included in the tests yet, see `tests/README` for more details. Coding guidelines ----------------- * python-hpilo currently supports python 2.4 up to python 3.5. Any new code in `hpilo.py` and `hpilo_cli` needs to be compatible with all these versions. That means no `with` statement, no `sorted` and using brackets for `print()`. Code in examples and tests can assume python 2.7 and 3.4 or newer. * No dependencies in `hpilo.py` and `hpilo_cli`. Examples may have additional dependencies. * All methods call into :func:`_info_tag` or :func:`_control_tag`. Any new method must do so too, to be able to use it in :meth:`call_delayed`. * All new methods must be documented. A docstring is mandatory and will appear in the docs. For methods that return data, sample output must be added to the documentation too. * All new methods must be tested. You should add data for the xml parser/generator tests and, if applicable, a test that manipulates the iLO. See the `tests/README` file in the git repository for more details on tests. .. _GitHub: https://github.com/seveas/python-hpilo python-hpilo-3.6/docs/shell.rst0000644000175000017500000001170012652734620017375 0ustar dennisdennis00000000000000Access from the shell ===================== The commandline interface, :program:`hpilo_cli`, allows you to make calls from your shell or scripts written in another language than python. It supports all methods that the library has. ``hpilo_cli`` usage ------------------- .. highlight:: console .. code-block:: console hpilo_cli [options] hostname method [args...] [ + method [args...]...] hpilo_cli download_rib_firmware ilotype version [version...] Contacts the iLO, calls one or more methods and displays the output as if you were using a python console. Options: -l LOGIN, --login=LOGIN Username to access the iLO -p PASSWORD, --password=PASSWORD Password to access the iLO -i, --interactive Prompt for username and/or password if they are not specified. -c FILE, --config=FILE File containing authentication and config details -t TIMEOUT, --timeout=TIMEOUT Timeout for iLO connections -j, --json Output a json document instead of a python dict -y, --yaml Output a yaml document instead of a python dict -P PROTOCOL, --protocol=PROTOCOL Use the specified protocol instead of autodetecting -d, --debug Output debug information, repeat to see all XML data -o PORT, --port=PORT SSL port to connect to --untested Allow untested methods -h, --help show this help message or help for a method -H, --help-methods show all supported methods :program:`hpilo_cli` will read a config file (by default :file:`~/.ilo.conf`) to find login information and any other variable you wish to set. This config file is a simple ini file that should look like this .. code-block:: ini [ilo] login = Administrator password = AdminPassword Using such a file is recommended over using the login/password commandline arguments. Many methods that can be called requier arguments. These arguments must be specified as :data:`key=value` pairs on the command-line. These parameters can also point to arbitrary configuration variables using the :attr:`key='$section.option'` syntax. Finally, you can also call multiple methds at once by separating them with a :data:`+` Examples -------- As you can see, the :program:`hpilo_cli` program is quite versatile. Some examples will make it clearer how to use this application properly. Getting the status of the UID light:: $ hpilo_cli example-server.int.kaarsemaker.net get_uid_status >>> print(my_ilo.get_uid_status()) OFF Getting virtual cdrom status in JSON format:: $ hpilo_cli example-server.int.kaarsemaker.net get_vm_status --json {"write_protect": "NO", "vm_applet": "DISCONNECTED", "image_url": "", "boot_option": "NO_BOOT", "device": "CDROM", "image_inserted": "NO"} Setting the name of the server:: $ hpilo_cli example-server.int.kaarsemaker.net set_server_name name=example-server Displaying help for the :func:`get_host_data` method:: $ hpilo_cli --help get_host_data Ilo.get_host_data [decoded_only=True]: Get SMBIOS records that describe the host. By default only the ones where human readable information is available are returned. To get all records pass decoded_only=False Methods like :func:`mod_network_data` method require dicts for some arguments (e.g. :data:`static_route_`), you can use the following syntax:: $ hpilo_cli example-server.int.kaarsemaker.net mod_network_settings static_route_1.dest=1.2.3.4 static_route_1.gateway=10.10.10.254 Calling multiple methods:: $ hpilo_cli example-server.int.kaarsemaker.net get_uid_status + uid_control uid=No + get_uid_status >>> print(my_ilo.get_uid_status()) ON >>> my_ilo.uid_control(uid="No") >>> print(my_ilo.get_uid_status()) OFF Setting a licence key defined in the config file:: $ cat ~/.ilo.conf [ilo] login = Administrator password = AdminPass [license] ilo3_advanced = FAKEL-ICENS-EFORH-PILO3-XXXXX $ hpilo_cli example-server.int.kaarsemaker.net activate_license key='$license.ilo3_advanced' Using hponcfg to talk to the local iLO device to reset the password without knowing it:: $ hpilo_cli -P local localhost mod_user user_login=Administrator password=NewPassword ``-P local`` is optional when specifying localhost as hostname, so this works too:: $ hpilo_cli localhost mod_user user_login=Administrator password=NewPassword If hponcfg is not in the default install location and not in your :data:`$PATH` or :data:`%PATH%`, you can set an alternative path in the configuration file. .. code-block:: ini [ilo] hponcfg = /usr/local/bin/hponcfg Available methods ----------------- All methods available to the python API are also available to the command line. These methods are documented separately in further pages here and in the `ilo scripting guide`_ published by HP. .. _`hp`: http://www.hp.com/go/ilo .. _`ilo scripting guide`: http://www.hp.com/support/ilo4_cli_gde_en python-hpilo-3.6/docs/autofirmware.rst0000644000175000017500000000325412652734620021000 0ustar dennisdennis00000000000000Automated firmware updates ========================== Building on the :doc:`Elasticsearch ` example, we can now build automated updates for iLO firmware. The example application uses `beanstalk`_ and `azuki`_ to queue firmware updates and process them with as much parallelism as you want. Scheduling updates ------------------ If you run :command:`hpilo_firmware_update`, it will query elasticsearch to find iLOs with obsolete firmware and schedule updates. It's probably most useful to run this command in the same cronjob as the elasticsearch importer to schedule firmware updates as they come in. Checking the queue ------------------ Using the :command:`azuki` tool, you can check how many iLOs need to be upgraded:: $ azuki stats hpilo-upgrades hpilo-upgrades Connections: Producers: 0 Consumers: 1 Waiting: 0 Jobs: Delayed: 0 Ready: 1 Urgent: 0 Reserved: 1 Buried: 0 Deleted: 11 Total: 13 Doing the upgrades ------------------ To process the queue, you again use azuki:: $ azuki daemon hpilo-upgrades INFO:azuki:Waiting for job Upgrading example-server-1.int.kaarsemaker.net (10.10.10.42) from ilo3 1.70 to ilo3 1.85 ... This will keep running and process new items as they come in. You'll probably want to run it in screen or tmux so it stays on in the background. If you have lots of iLOs to upgrade, you can start as many instances of this as you want, they will not step on each others toes. I regularly run up to 30 instances in parallel in a tmux session. .. _`beanstalk`: http://kr.github.io/beanstalkd/ .. _`azuki`: http://github.com/seveas/azuki python-hpilo-3.6/docs/ca.rst0000644000175000017500000000725712652734620016665 0ustar dennisdennis00000000000000Managing SSL certificates ========================= When managing large amounts of iLO interfaces, the constant SSL warnings are a nuisance, so let's make sure we have proper SSL certificates. This script will make that easy to do for you by taking care of all the CA work. All you need to do is add the CA's certificate to your browsers trusted CA list. First thing to do is configure the CA. Add something like the following to your :file:`~/.ilo.conf`:: [ca] path = ~/.hpilo_ca country = NL state = Flevoland locality = Lelystad organization = Kaarsemaker.net organizational_unit = Sysadmin This path can point to an existing CA, the only requirement is that :file:`openssl.cnf` for this CA lives inside that directory. The other config values are used when generating the certificates for the iLOs and are all optional, they default to what HP puts in there. If the CA does not yet exist, you can create it as follows:: $ hpilo_ca init Generating RSA private key, 2048 bit long modulus .+++ ..................+++ e is 65537 (0x10001) You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [NL]: State or Province Name (full name) [Flevoland]: Locality Name (eg, city) [Lelystad]: Organization Name (eg, company) [Kaarsemaker.net]: Common Name (eg, your name or your servers hostname) [hpilo_ca]: This generates the needed directories, an openssl config and a self-signed certificate for your CA. When your CA is set up, you can start signing certificates. :file:`hpilo_ca` will check several things: * Firmware is upgraded if necessary * The hostname is set to the name you use to connect to it, if needed * iLO2 is configured to use FQDN's for certificate signing requests It will then download the certificate signing request, sign it and upload the signed certificate. Here's an example of it at work:: $ ./hpilo_ca sign example-server.int.kaarsemaker.net (1/5) Checking certificate config of example-server.int.kaarsemaker.net (2/5) Retrieving certificate signing request (3/5) Signing certificate Using configuration from /home/dennis/.hpilo_ca/openssl.cnf Check that the request matches the signature Signature ok Certificate Details: Serial Number: 4 (0x4) Validity Not Before: Oct 5 09:48:26 2015 GMT Not After : Oct 3 09:48:26 2020 GMT Subject: countryName = NL stateOrProvinceName = Flevoland organizationName = Kaarsemaker.net organizationalUnitName = Sysadmin commonName = example-server.int.kaarsemaker.net X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: 59:E5:B8:37:C5:30:8D:38:47:29:3E:C1:0E:B3:0A:97:95:48:3E:D1 X509v3 Authority Key Identifier: keyid:89:17:37:C5:E3:2D:EA:5C:83:0A:52:36:79:B0:EC:B7:A4:D5:D4:EF Netscape Comment: Certificate generated by iLO CA X509v3 Subject Alternative Name DNS:example-server.int.kaarsemaker.net, DNS:example-server, IP Address:10.4.2.13 Certificate is to be certified until Oct 3 09:48:26 2020 GMT (1825 days) Write out database with 1 new entries Data Base Updated (4/5) Uploading certificate (5/5) Resetting iLO python-hpilo-3.6/docs/xmldata.rst0000644000175000017500000000100112652734620017711 0ustar dennisdennis00000000000000Unauthenticated iLO and Chassis OA data ======================================= Unless you have disabled it, both server/blade iLO's and chassis onboard administrators, expose a lot of basic information on an unauthenticated https url. While not technically part of the iLO API, this is still a useful function to have, and is the only way to programmatically get data from an onboard Administrator. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: xmldata .. ilo_output:: xmldata python-hpilo-3.6/docs/index.rst0000644000175000017500000000737712652734620017414 0ustar dennisdennis00000000000000iLO automation from python or shell =================================== HP servers come with a powerful out of band management interface called Integrated Lights out, or iLO. It has an extensive web interface and commercially available tools for centrally managing iLO devices and their servers. But if you want to built your own tooling, integrate iLO management to your existing procedures or simply want to manage iLOs using a command-line interface, you're stuck manually creating XML files and using a perl hack HP ships called locfg.pl. Enter python-hpilo! Using the same XML interface as HP's own management tools, here is a python library and command-line tool that make it a lot easier to do all the above. No manual XML writing, just call functions from either python or your shell(script). Quick usage examples ==================== Full usage documentation can be found following the links below, but here are some examples to wet your appetite: Getting the chassis IP of a blade server, from python:: >>> ilo = hpilo.Ilo('example-server.int.kaarsemaker.net') >>> chassis = ilo.get_oa_info() >>> print chassis['ipaddress'] 10.42.128.101 Entering a license key and creating a user, from the shell: .. code-block:: console $ hpilo_cli example-server.int.kaarsemaker.net activate_license key=$mykey $ hpilo_cli example-server.int.kaarsemaker.net add_user user_login=dennis \ password=hunter2 admin_priv=true The available functions you can call are all documented in the pages linked below, but for detailed descriptions of all functions and especially their arguments, please refer to the `ilo scripting guide`_ as well. This package also ships examples of more complete applications in the examples directory. This include an automated CA for managing SSL certificates, tooling to centralize iLO informatin in elastic search and an automated firmware updater. All of which are used in production by the author or other contributors. Compatibility ============= This module is written with compatibility as main priority. Currently supported are: * All RILOE II/iLO versions up to and including iLO 4 * Python 2.4-2.7 and python 3.2 and newer * Any operating system Python runs on iLOs can be managed both locally using `hponcfg` or remotely using the iLO's built-in webserver. In the latter case, the requirements above concern the machine you run this code on, not the managed server. Getting started =============== .. toctree:: :maxdepth: 1 install python shell Available functionality ======================= .. toctree:: :maxdepth: 1 info networksettings license authentication security health power boot media input snmp firmware xmldata log federation ahs profile Example applications ==================== There are several example applications in the `examples/` directory. Note that while `hpilo.py` and `hpilo_cli` are compatible with python versions as old as 2.4, some examples may require new versions of python and have additional dependencies. .. toctree:: :maxdepth: 1 ca elasticsearch autofirmware puppet Development information ======================= .. toctree:: :maxdepth: 1 troubleshooting contributing Author and license ================== This software is (c) 2011-2016 Dennis Kaarsemaker This program 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. HP, Integrated Lights out and iLO are trademarks of HP, with whom the author of this software is not affiliated in any way. .. _`ilo scripting guide`: http://www.hp.com/support/ilo4_cli_gde_en python-hpilo-3.6/docs/media.rst0000644000175000017500000000100512652734620017342 0ustar dennisdennis00000000000000Virtual media ============= The iLO can make an iso file located on another machine available to the server as virtual floppy or cdrom device. This can be used to e.g. install an operating system remotely. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_vm_status .. ilo_output:: get_vm_status .. automethod:: set_vf_status .. automethod:: set_vm_status .. automethod:: insert_virtual_media .. automethod:: eject_virtual_floppy .. automethod:: eject_virtual_media python-hpilo-3.6/docs/conf.py0000644000175000017500000001606612652734620017045 0ustar dennisdennis00000000000000# -*- coding: utf-8 -*- # # python-hpilo documentation build configuration file, created by # sphinx-quickstart on Thu Dec 1 00:46:51 2011. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os import cloud_sptheme as csp # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'ilodoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'python-hpilo' copyright = u'2011-2016, Dennis Kaarsemaker' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '3.6' # The full version, including alpha/beta/rc tags. release = '3.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'cloud' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. html_theme_options = { 'roottarget': 'index', 'stickysidebar': False, } # Add any paths that contain custom themes here, relative to this directory. html_theme_path = [csp.get_theme_dir()] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. html_logo = '_static/python-hpilo.png' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. html_show_sphinx = False # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'python-hpilodoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'python-hpilo.tex', u'python-hpilo Documentation', u'Dennis Kaarsemaker', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'python-hpilo', u'python-hpilo Documentation', [u'Dennis Kaarsemaker'], 1) ] python-hpilo-3.6/docs/log.rst0000644000175000017500000000101612652734620017046 0ustar dennisdennis00000000000000iLO event log ============= The iLO keeps two separate logs: for iLO events and for server events. While iLO 4 can also log to a central syslog server, for others you will need to query this log yourself, using the functions below. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_ilo_event_log .. ilo_output:: get_ilo_event_log .. automethod:: clear_ilo_event_log .. automethod:: get_server_event_log .. ilo_output:: get_server_event_log .. automethod:: clear_server_event_log python-hpilo-3.6/docs/security.rst0000644000175000017500000000153612652734620020143 0ustar dennisdennis00000000000000Security and SSL settings ========================= With these functions, you can ensure your iLO's security settings are as secure as you want them, including using proper SSL certificates for communication. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: cert_fqdn .. automethod:: get_cert_subject_info .. ilo_output:: get_cert_subject_info .. automethod:: certificate_signing_request .. automethod:: import_certificate .. automethod:: computer_lock_config .. automethod:: fips_enable .. automethod:: get_encrypt_settings .. ilo_output:: get_encrypt_settings .. automethod:: get_fips_status .. ilo_output:: get_fips_status .. automethod:: get_security_msg .. ilo_output:: get_security_msg .. automethod:: set_security_msg .. automethod:: get_tpm_status .. ilo_output:: get_tpm_status python-hpilo-3.6/docs/install.rst0000644000175000017500000000414112652734620017735 0ustar dennisdennis00000000000000Installing python-hpilo ======================= This module is easy to install and has very few extra dependencies. For the convenience of users of major linux distributions, I also ship packages that you can install with the standard package manager. Dependencies ------------ Always needed: * `Python`_ 2.4 or newer, up to python 3.4 * When using python 2.4, you need to install the `cElementTree`_ library separately. Python 2.5 or newer already include this library. Sometimes needed: * If you want to use the ``LOCAL`` protocol, talking to the iLO from the server it is installed in via a kernel driver, you need to install this driver and the ``hponcfg`` tool from `hp`_ * Some example applications require additional software. More details about these requirements can be found in the documentation of those examples. .. _`python`: http://www.python.org .. _`cElementTree`: http://effbot.org/zone/celementtree.htm .. _`hp`: http://www.hp.com/go/ilo Installing the latest release ----------------------------- When using Ubuntu, Debian, Fedora, CentOS or RHEL, it is advisable to use the deb or rpm packages I create for every release, so you get automatic updates whenever a new release is issued. Users of Ubuntu releases that Canonical still supports can use my launchpad PPA: .. code-block:: console $ sudo add-apt-repository ppa:dennis/python $ sudo apt-get update $ sudo apt-get install python-hpilo Users of other Ubuntu releases, Debian, Fedora, CentOS or RHEL can use the repositories on OpenBuildService, instructions can be found on the `obs site`_ If you can not, or do not want to use these packages (for example, if you use windows or osx, or if you want to install into a virtualenv) you can download the package from `PyPI`_ and install it manually like any other application by unpacking it and running ``python setup.py install``. Or use ``pip`` to install it: ``pip install python-hpilo`` .. _`obs site`: http://software.opensuse.org/download.html?project=home%3Aseveas%3Apython&package=python-hpilo .. _`PyPI`: http://pypi.python.org/packages/source/p/python-hpilo/, extract it and run python-hpilo-3.6/docs/Makefile0000644000175000017500000001100612652734620017173 0ustar dennisdennis00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-hpilo.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-hpilo.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/python-hpilo" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/python-hpilo" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." python-hpilo-3.6/docs/authentication.rst0000644000175000017500000000222212652734620021304 0ustar dennisdennis00000000000000Authentication settings ======================= By default, an iLO has only one user account: Administrator. But via the API you can create more users and manipulate them. It's also possible to import SSH keys, configure kerberos settings and configure single-sign on. Some methods accept a lot of arguments, for details on what these arguments mean, I will refer to the `ilo scripting guide`_. .. _`ilo scripting guide`: http://www.hp.com/support/ilo4_cli_gde_en .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_all_users .. ilo_output:: get_all_users .. automethod:: get_all_user_info .. ilo_output:: get_all_user_info .. automethod:: get_user .. ilo_output:: get_user .. automethod:: add_user .. automethod:: mod_user .. automethod:: delete_user .. automethod:: import_ssh_key .. automethod:: delete_ssh_key .. automethod:: get_dir_config .. ilo_output:: get_dir_config .. automethod:: mod_dir_config .. automethod:: get_sso_settings .. ilo_output:: get_sso_settings .. automethod:: mod_sso_settings .. automethod:: get_twofactor_settings .. ilo_output:: get_twofactor_settings python-hpilo-3.6/docs/health.rst0000644000175000017500000000071712652734620017541 0ustar dennisdennis00000000000000Server health ============= The iLO knows a lot about your server's physical health. The :meth:`get_embedded_health` method lets you retrieve all the health information, so you can act upon it, for example in monitoring checks and management scripts. Note that the returned data can differ significantly between iLO versions. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_embedded_health .. ilo_output:: get_embedded_health python-hpilo-3.6/docs/power.rst0000644000175000017500000000226012652734620017423 0ustar dennisdennis00000000000000Power manipulation ================== The power settings and usage of to the server can be inspected using these methods. It is also possible to power the server on and off via the iLO, and to :doc:`boot documentation `. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: press_pwr_btn .. automethod:: hold_pwr_btn .. automethod:: get_host_power_status .. ilo_output:: get_host_power_status .. automethod:: set_host_power .. automethod:: get_server_auto_pwr .. ilo_output:: get_server_auto_pwr .. automethod:: set_server_auto_pwr .. automethod:: get_power_readings .. ilo_output:: get_power_readings .. automethod:: get_server_power_on_time .. ilo_output:: get_server_power_on_time .. automethod:: clear_server_power_on_time .. automethod:: get_host_power_saver_status .. ilo_output:: get_host_power_saver_status .. automethod:: set_host_power_saver .. automethod:: get_power_cap .. ilo_output:: get_power_cap .. automethod:: set_power_cap .. automethod:: get_host_pwr_micro_ver .. ilo_output:: get_host_pwr_micro_ver .. automethod:: get_pwreg .. ilo_output:: get_pwreg .. automethod:: set_pwreg python-hpilo-3.6/docs/output/0000755000175000017500000000000012652734620017075 5ustar dennisdennis00000000000000python-hpilo-3.6/docs/output/get_uid_status0000644000175000017500000000000412652734620022035 0ustar dennisdennis00000000000000OFF python-hpilo-3.6/docs/output/get_server_event_log0000644000175000017500000000256412652734620023236 0ustar dennisdennis00000000000000[{'class': 'Maintenance', 'count': 1, 'description': 'Maintenance note: IML cleared through hpasmcli', 'event_class': '0x0021', 'event_code': '0x0002', 'initial_update': '04/10/2014 12:26', 'last_update': '04/10/2014 12:26', 'severity': 'Informational'}, {'class': 'Rack Infrastructure', 'count': 1, 'description': 'Chassis Enclosure Serial Number SGH035M712 requires minimum firmware revision 03.50. It is currently 03.32.', 'event_class': '0x0022', 'event_code': '0x0019', 'initial_update': '[NOT SET] ', 'last_update': '[NOT SET] ', 'severity': 'Caution'}, {'class': 'POST Message', 'count': 1, 'description': 'POST Error: 1785-Slot X Drive Array Not Configured', 'event_class': '0x000a', 'event_code': '0x0001', 'initial_update': '12/20/2013 00:03', 'last_update': '12/20/2013 00:03', 'severity': 'Caution'}, {'class': 'System Revision', 'count': 1, 'description': 'Firmware flashed (ProLiant System BIOS - I31 08/02/2014)', 'event_class': '0x0020', 'event_code': '0x0002', 'initial_update': '03/05/2015 09:38', 'last_update': '03/05/2015 09:38', 'severity': 'Informational'}, {'class': 'System Revision', 'count': 1, 'description': 'Firmware flashed (iLO 4 2.10)', 'event_class': '0x0020', 'event_code': '0x0002', 'initial_update': '04/08/2015 16:55', 'last_update': '04/08/2015 16:55', 'severity': 'Informational'}] python-hpilo-3.6/docs/output/get_twofactor_settings0000644000175000017500000000013712652734620023610 0ustar dennisdennis00000000000000{'auth_twofactor_enable': False, 'cert_owner_subject': None, 'cert_revocation_check': False} python-hpilo-3.6/docs/output/get_network_settings0000644000175000017500000000427012652734620023273 0ustar dennisdennis00000000000000{'dhcp_dns_server': True, 'dhcp_domain_name': True, 'dhcp_enable': True, 'dhcp_gateway': True, 'dhcp_sntp_settings': True, 'dhcp_static_route': True, 'dhcp_wins_server': True, 'dhcpv6_dns_server': True, 'dhcpv6_domain_name': False, 'dhcpv6_rapid_commit': False, 'dhcpv6_sntp_settings': True, 'dhcpv6_stateful_enable': True, 'dhcpv6_stateless_enable': True, 'dns_name': 'example-server', 'domain_name': 'int.kaarsemaker.net', 'enable_nic': True, 'full_duplex': 'Automatic', 'gateway_ip_address': '10.42.128.254', 'ilo_nic_auto_select': 'DISABLED', 'ip_address': '10.42.128.100', 'ipv6_addr_autocfg': True, 'ipv6_address': 'fe80::9eb6:54ff:fe8e:4b7c', 'ipv6_default_gateway': '::', 'ipv6_preferred_protocol': True, 'ipv6_prim_dns_server': '::', 'ipv6_reg_ddns_server': True, 'ipv6_sec_dns_server': '::', 'ipv6_static_route_1': {'addr_status': 'INACTIVE', 'ipv6_dest': '::', 'ipv6_gateway': '::', 'prefixlen': 0}, 'ipv6_static_route_2': {'addr_status': 'INACTIVE', 'ipv6_dest': '::', 'ipv6_gateway': '::', 'prefixlen': 0}, 'ipv6_static_route_3': {'addr_status': 'INACTIVE', 'ipv6_dest': '::', 'ipv6_gateway': '::', 'prefixlen': 0}, 'ipv6_ter_dns_server': '::', 'mac_address': '9c:b6:54:8e:4b:7c', 'nic_speed': 'Automatic', 'ping_gateway': True, 'prim_dns_server': '10.42.128.1', 'prim_wins_server': '0.0.0.0', 'reg_ddns_server': True, 'reg_wins_server': True, 'sec_dns_server': '0.0.0.0', 'sec_wins_server': '0.0.0.0', 'sntp_server1': '10.42.128.1', 'sntp_server2': '10.42.128.2', 'speed_autoselect': True, 'static_route_1': {'dest': '0.0.0.0', 'gateway': '0.0.0.0', 'mask': '0.0.0.0'}, 'static_route_2': {'dest': '0.0.0.0', 'gateway': '0.0.0.0', 'mask': '0.0.0.0'}, 'static_route_3': {'dest': '0.0.0.0', 'gateway': '0.0.0.0', 'mask': '0.0.0.0'}, 'subnet_mask': '255.255.255.0', 'ter_dns_server': '0.0.0.0', 'timezone': 'Atlantic/Reykjavik'} python-hpilo-3.6/docs/output/get_asset_tag_10000644000175000017500000000003112652734620022043 0ustar dennisdennis00000000000000{'asset_tag': 'NL00001'} python-hpilo-3.6/docs/output/get_user0000644000175000017500000000033612652734620020637 0ustar dennisdennis00000000000000user_login='Administrator' {'admin_priv': True, 'config_ilo_priv': True, 'remote_cons_priv': True, 'reset_server_priv': True, 'user_login': 'Administrator', 'user_name': 'Administrator', 'virtual_media_priv': True} python-hpilo-3.6/docs/output/get_smh_fqdn0000644000175000017500000000004312652734620021453 0ustar dennisdennis00000000000000example-server.int.kaarsemaker.net python-hpilo-3.6/docs/output/get_rack_settings0000644000175000017500000000030112652734620022511 0ustar dennisdennis00000000000000{'bay': 9, 'enclosure_name': 'CHASSIS-225', 'enclosure_sn': 'CZ1234ABCD', 'enclosure_type': 'BladeSystem c7000 Enclosure G2', 'enclosure_uuid': '09CZ1234ABCD', 'rack_name': 'CHASSIS-225'} python-hpilo-3.6/docs/output/get_server_fqdn0000644000175000017500000000004312652734620022172 0ustar dennisdennis00000000000000example-server.int.kaarsemaker.net python-hpilo-3.6/docs/output/get_power_readings0000644000175000017500000000024512652734620022670 0ustar dennisdennis00000000000000{'average_power_reading': (65, 'Watts'), 'maximum_power_reading': (101, 'Watts'), 'minimum_power_reading': (65, 'Watts'), 'present_power_reading': (67, 'Watts')} python-hpilo-3.6/docs/output/get_federation_all_groups0000644000175000017500000000001412652734620024221 0ustar dennisdennis00000000000000['DEFAULT'] python-hpilo-3.6/docs/output/get_all_languages0000644000175000017500000000010112652734620022445 0ustar dennisdennis00000000000000{'language_selection': {'lang_id': 'en', 'language': 'English'}} python-hpilo-3.6/docs/output/get_sso_settings0000644000175000017500000000145612652734620022411 0ustar dennisdennis00000000000000{'administrator_role': {'admin_priv': True, 'cfg_ilo_priv': True, 'login_priv': True, 'remote_cons_priv': True, 'reset_server_priv': True, 'virtual_media_priv': True}, 'operator_role': {'admin_priv': False, 'cfg_ilo_priv': False, 'login_priv': True, 'remote_cons_priv': True, 'reset_server_priv': True, 'virtual_media_priv': True}, 'trust_mode': 'DISABLED', 'user_role': {'admin_priv': False, 'cfg_ilo_priv': False, 'login_priv': True, 'remote_cons_priv': False, 'reset_server_priv': False, 'virtual_media_priv': False}} python-hpilo-3.6/docs/output/get_hotkey_config0000644000175000017500000000035212652734620022507 0ustar dennisdennis00000000000000{'ctrl_t': 'NONE,NONE,NONE,NONE,NONE', 'ctrl_u': 'NONE,NONE,NONE,NONE,NONE', 'ctrl_v': 'NONE,NONE,NONE,NONE,NONE', 'ctrl_w': 'NONE,NONE,NONE,NONE,NONE', 'ctrl_x': 'NONE,NONE,NONE,NONE,NONE', 'ctrl_y': 'NONE,NONE,NONE,NONE,NONE'} python-hpilo-3.6/docs/output/get_all_user_info0000644000175000017500000000050112652734620022474 0ustar dennisdennis00000000000000{'Administrator': {'admin_priv': True, 'config_ilo_priv': True, 'remote_cons_priv': True, 'reset_server_priv': True, 'user_login': 'Administrator', 'user_name': 'Administrator', 'virtual_media_priv': True}} python-hpilo-3.6/docs/output/get_pwreg0000644000175000017500000000023412652734620021002 0ustar dennisdennis00000000000000{'efficiency_mode': 3, 'get_host_power': {'host_power': 'ON'}, 'pcap': {'mode': 'OFF'}, 'pwralert': {'duration': 0, 'threshold': 0, 'type': 'DISABLED'}} python-hpilo-3.6/docs/output/get_federation_all_groups_info0000644000175000017500000000041412652734620025240 0ustar dennisdennis00000000000000{'DEFAULT': {'admin_priv': False, 'config_ilo_priv': False, 'group_name': 'DEFAULT', 'login_priv': True, 'remote_cons_priv': False, 'reset_server_priv': False, 'virtual_media_priv': False}} python-hpilo-3.6/docs/output/get_federation_group0000644000175000017500000000031512652734620023212 0ustar dennisdennis00000000000000group_name="DEFAULT" {'admin_priv': False, 'config_ilo_priv': False, 'group_name': 'DEFAULT', 'login_priv': True, 'remote_cons_priv': False, 'reset_server_priv': False, 'virtual_media_priv': False} python-hpilo-3.6/docs/output/get_federation_multicast0000644000175000017500000000021412652734620024061 0ustar dennisdennis00000000000000{'ipv6_multicast_scope': 'Site', 'multicast_announcement_interval': 'Disabled', 'multicast_discovery_enabled': 'No', 'multicast_ttl': 5} python-hpilo-3.6/docs/output/get_fw_version0000644000175000017500000000020212652734620022032 0ustar dennisdennis00000000000000{'firmware_date': 'Jan 15 2015', 'firmware_version': '2.10', 'license_type': 'iLO 4 Advanced', 'management_processor': 'iLO4'} python-hpilo-3.6/docs/output/get_ahs_status0000644000175000017500000000013112652734620022030 0ustar dennisdennis00000000000000{'ahs_hardware_status': 'ENABLED', 'ahs_status': 'ENABLED', 'temp_ahs_disabled': 'NO'} python-hpilo-3.6/docs/output/get_persistent_boot0000644000175000017500000000005512652734620023102 0ustar dennisdennis00000000000000['cdrom', 'floppy', 'usb', 'hdd', 'network'] python-hpilo-3.6/docs/output/get_cert_subject_info0000644000175000017500000000055212652734620023350 0ustar dennisdennis00000000000000{'csr_subject_common_name': 'example-server.int.kaarsemaker.net', 'csr_subject_country': 'US', 'csr_subject_location': 'Houston', 'csr_subject_org_name': 'Hewlett-Packard Development Company', 'csr_subject_orgunit_name': 'ISS', 'csr_subject_state': 'Texas', 'csr_use_cert_2048pkey': 'NO', 'csr_use_cert_custom_subject': 'NO', 'csr_use_cert_fqdn': 'YES'} python-hpilo-3.6/docs/output/xmldata0000644000175000017500000000427412652734620020461 0ustar dennisdennis00000000000000{'bladesystem': {'bay': 4, 'manager': {'encl': 'OA-002655FF2F7B', 'mgmtipaddr': '10.42.128.101', 'rack': 'UnnamedRack', 'st': 2, 'type': 'Onboard Administrator'}}, 'health': {'status': 2}, 'hsi': {'cuuid': '30313436-3631-5A43-3334-313534343843', 'nics': [{'description': 'iLO 4', 'ipaddr': '10.42.128.100', 'location': 'Embedded', 'macaddr': '9c:b6:54:8e:4b:7c', 'port': 1, 'status': 'OK'}, {'description': 'N/A', 'ipaddr': 'N/A', 'location': 'Embedded', 'macaddr': 'fc:15:b4:0a:9d:58', 'port': 1, 'status': 'Unknown'}, {'description': 'N/A', 'ipaddr': 'N/A', 'location': 'Embedded', 'macaddr': 'fc:15:b4:0a:9d:5c', 'port': 2, 'status': 'Unknown'}], 'productid': ' 641016-B21 ', 'sbsn': 'CZ3415448C ', 'sp': 1, 'spn': 'ProLiant BL460c Gen8', 'uuid': '641016CZ3415448C', 'virtual': {'state': 'Inactive', 'vid': {'bsn': None, 'cuuid': None}}}, 'mp': {'bblk': '03/05/2013', 'ealert': 1, 'ers': 0, 'fwri': '2.10', 'hwri': 'ASIC: 16', 'ipm': 1, 'pn': 'Integrated Lights-Out 4 (iLO 4)', 'pwrm': '3.3', 'sn': 'ILOCZ3415448C ', 'sso': 0, 'st': 1, 'uuid': 'ILO641016CZ3415448C'}, 'spatial': {'bay': 4, 'cuuid': '30313436-3631-5A43-3334-313534343843', 'discovery_data': 'Unknown data', 'discovery_rack': 'Not Supported', 'enclosure_cuuid': '42473930-3038-3430-4850-523000000000', 'rack_description': 0, 'rack_id': 0, 'rack_id_pn': 0, 'rack_uheight': 0, 'tag_version': 0, 'uheight': 0, 'ulocation': 0, 'uoffset': 0, 'uposition': 0}} python-hpilo-3.6/docs/output/get_vm_status0000644000175000017500000000022012652734620021676 0ustar dennisdennis00000000000000{'boot_option': 'NO_BOOT', 'device': 'CDROM', 'image_inserted': 'NO', 'image_url': '', 'vm_applet': 'DISCONNECTED', 'write_protect': 'NO'} python-hpilo-3.6/docs/output/get_asset_tag0000644000175000017500000000023112652734620021625 0ustar dennisdennis00000000000000/home/dennis/code/python-hpilo/hpilo.py:459: IloWarning: No Asset Tag Information. warnings.warn(child.get('MESSAGE'), IloWarning) {'asset_tag': None} python-hpilo-3.6/docs/output/xmldata_10000644000175000017500000062646512652734620020715 0ustar dennisdennis00000000000000>>> pprint(my_ilo.xmldata()) {'infra2': {'addr': 'A9FE0106', 'asset': None, 'blades': {'bays': [{'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 0, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 56, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 112, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 168, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 224, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 280, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 336, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 392, 'mmyoffset': 7, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 0, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 56, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 112, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 168, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 224, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 280, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 336, 'mmyoffset': 188, 'side': 'FRONT'}, {'mmdepth': 480, 'mmheight': 181, 'mmwidth': 56, 'mmxoffset': 392, 'mmyoffset': 188, 'side': 'FRONT'}], 'blades': [{'associatedblade': 0, 'bay': {'connection': 2, 'occupies': [10, 1, 9]}, 'bsn': 'CZ3238WP9S', 'conjoinable': False, 'cuuid': '37333436-3538-5A43-3332-333857503953', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.100', 'portmap': {'mezz': [{'device': {'name': 'QLogic QMH2562 8Gb FC HBA for HP BladeSystem c-Class', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:9b:04'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:9b:06'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 2}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 2}, {'number': 3, 'traybaynumber': 3, 'trayportnumber': 10}, {'number': 4, 'traybaynumber': 4, 'trayportnumber': 10}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'device': {'name': 'QLogic QMH2562 8Gb FC HBA for HP BladeSystem c-Class', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:bd:08'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:bd:0a'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 2}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 2}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 2}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 2}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'number': 3, 'slot': {'port': [{'number': 1, 'traybaynumber': 7, 'trayportnumber': 10}, {'number': 2, 'traybaynumber': 8, 'trayportnumber': 10}, {'number': 3, 'traybaynumber': 5, 'trayportnumber': 10}, {'number': 4, 'traybaynumber': 6, 'trayportnumber': 10}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'number': 4, 'slot': {'port': [{'number': 1, 'traybaynumber': 7, 'trayportnumber': 1}, {'number': 2, 'traybaynumber': 8, 'trayportnumber': 1}, {'number': 3, 'traybaynumber': 5, 'trayportnumber': 1}, {'number': 4, 'traybaynumber': 6, 'trayportnumber': 1}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'number': 5, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 9}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 9}, {'number': 3, 'traybaynumber': 3, 'trayportnumber': 1}, {'number': 4, 'traybaynumber': 4, 'trayportnumber': 1}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 6, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 1}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 1}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 7, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 9}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 9}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 9}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 9}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:A0', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:A1', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:A1', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:A1', 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:A0'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:A4', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:A5', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:A5', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:A5', 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:A4'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:A8', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:A9', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:A9', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:A9', 'number': 3, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:A1'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:AC', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:AD', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:AD', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:AD', 'number': 4, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:A5'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:25:30', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:25:31', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:25:31', 'type': 'G'}], 'iscsi': 'E8:39:35:18:25:31', 'number': 5, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:A8'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:25:34', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:25:35', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:25:35', 'type': 'G'}], 'iscsi': 'E8:39:35:18:25:35', 'number': 6, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:AC'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 10}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 10}, {'number': 3, 'traybaynumber': 1, 'trayportnumber': 2}, {'number': 4, 'traybaynumber': 2, 'trayportnumber': 2}, {'number': 5, 'traybaynumber': 1, 'trayportnumber': 9}, {'number': 6, 'traybaynumber': 2, 'trayportnumber': 9}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 1800, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL680c G7', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 42, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 46, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '643785CZ3238WP9S', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 3}, 'bsn': 'CZ3316C67H', 'conjoinable': False, 'cuuid': '30313436-3631-5A43-3333-313643363748', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.101', 'portmap': {'mezz': [{'device': {'name': 'QLogic QMH2572 8Gb FC HBA for HP BladeSystem c-Class', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:22:73:51:d0'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:22:73:51:d2'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 3}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 3}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'device': {'name': 'QLogic QMH2572 8Gb FC HBA for HP BladeSystem c-Class', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:16:7d:d9:1c'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:16:7d:d9:1e'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 3}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 3}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 3}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 3}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': '6C:3B:E5:BC:57:D8', 'type': 'C'}, {'function': 98, 'guid_string': '6C:3B:E5:BC:57:D9', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:6C:3B:E5:BC:57:D9', 'type': 'G'}], 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': '6C:3B:E5:BC:57:D8'}, {'guids': [{'function': 97, 'guid_string': '6C:3B:E5:BC:57:DC', 'type': 'C'}, {'function': 98, 'guid_string': '6C:3B:E5:BC:57:DD', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:6C:3B:E5:BC:57:DD', 'type': 'G'}], 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': '6C:3B:E5:BC:57:DC'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 3}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 3}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 287, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL460c Gen8', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '641016CZ3316C67H', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 4}, 'bsn': 'CZ3415448C', 'conjoinable': False, 'cuuid': '30313436-3631-5A43-3334-313534343843', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.102', 'portmap': {'mezz': [{'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 4}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 4}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 4}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 4}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 4}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 4}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'FC:15:B4:0A:9D:58', 'type': 'C'}, {'function': 98, 'guid_string': 'FC:15:B4:0A:9D:59', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:FC:15:B4:0A:9D:59', 'type': 'G'}], 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'FC:15:B4:0A:9D:58'}, {'guids': [{'function': 97, 'guid_string': 'FC:15:B4:0A:9D:5C', 'type': 'C'}, {'function': 98, 'guid_string': 'FC:15:B4:0A:9D:5D', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:FC:15:B4:0A:9D:5D', 'type': 'G'}], 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'FC:15:B4:0A:9D:5C'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 4}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 4}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 281, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL460c Gen8', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '641016CZ3415448C', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 6, 'occupies': [14, 5, 13]}, 'bsn': 'CZ3238WP85', 'conjoinable': False, 'cuuid': '37333436-3538-5A43-3332-333857503835', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.103', 'portmap': {'mezz': [{'device': {'name': 'QLogic QMH2562 8Gb FC HBA for HP BladeSystem c-Class', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:be:d8'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:be:da'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 6}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 6}, {'number': 3, 'traybaynumber': 3, 'trayportnumber': 14}, {'number': 4, 'traybaynumber': 4, 'trayportnumber': 14}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'device': {'name': 'QLogic QMH2562 8Gb FC HBA for HP BladeSystem c-Class', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:ba:e0'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:18:70:ba:e2'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 6}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 6}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 6}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 6}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'number': 3, 'slot': {'port': [{'number': 1, 'traybaynumber': 7, 'trayportnumber': 14}, {'number': 2, 'traybaynumber': 8, 'trayportnumber': 14}, {'number': 3, 'traybaynumber': 5, 'trayportnumber': 14}, {'number': 4, 'traybaynumber': 6, 'trayportnumber': 14}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'number': 4, 'slot': {'port': [{'number': 1, 'traybaynumber': 7, 'trayportnumber': 5}, {'number': 2, 'traybaynumber': 8, 'trayportnumber': 5}, {'number': 3, 'traybaynumber': 5, 'trayportnumber': 5}, {'number': 4, 'traybaynumber': 6, 'trayportnumber': 5}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'number': 5, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 13}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 13}, {'number': 3, 'traybaynumber': 3, 'trayportnumber': 5}, {'number': 4, 'traybaynumber': 4, 'trayportnumber': 5}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 6, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 5}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 5}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 7, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 13}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 13}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 13}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 13}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:58', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:59', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:59', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:59', 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:58'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:5C', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:5D', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:5D', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:5D', 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:5C'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:60', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:61', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:61', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:61', 'number': 3, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:59'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:6F:64', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:6F:65', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:6F:65', 'type': 'G'}], 'iscsi': 'E8:39:35:18:6F:65', 'number': 4, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:5D'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:27:90', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:27:91', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:27:91', 'type': 'G'}], 'iscsi': 'E8:39:35:18:27:91', 'number': 5, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:60'}, {'guids': [{'function': 97, 'guid_string': 'E8:39:35:18:27:94', 'type': 'C'}, {'function': 98, 'guid_string': 'E8:39:35:18:27:95', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:E8:39:35:18:27:95', 'type': 'G'}], 'iscsi': 'E8:39:35:18:27:95', 'number': 6, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'E8:39:35:18:6F:64'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 14}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 14}, {'number': 3, 'traybaynumber': 1, 'trayportnumber': 6}, {'number': 4, 'traybaynumber': 2, 'trayportnumber': 6}, {'number': 5, 'traybaynumber': 1, 'trayportnumber': 13}, {'number': 6, 'traybaynumber': 2, 'trayportnumber': 13}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 489, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL680c G7', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 42, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 46, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '643785CZ3238WP85', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_UNKNOWN', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_UNKNOWN', 'floppyurl': None, 'support': 'VM_NOT_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 7}, 'bsn': 'CZ34091CNJ', 'conjoinable': False, 'cuuid': '30313436-3631-5A43-3334-303931434E4A', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.104', 'portmap': {'mezz': [{'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 7}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 7}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 7}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 7}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 7}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 7}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'FC:15:B4:09:12:E8', 'type': 'C'}, {'function': 98, 'guid_string': 'FC:15:B4:09:12:E9', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:FC:15:B4:09:12:E9', 'type': 'G'}], 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'FC:15:B4:09:12:E8'}, {'guids': [{'function': 97, 'guid_string': 'FC:15:B4:09:12:EC', 'type': 'C'}, {'function': 98, 'guid_string': 'FC:15:B4:09:12:ED', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:FC:15:B4:09:12:ED', 'type': 'G'}], 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'FC:15:B4:09:12:EC'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 7}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 7}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 293, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL460c Gen8', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 42, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 46, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '641016CZ34091CNJ', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 8}, 'bsn': 'CZ3342RYTH', 'conjoinable': False, 'cuuid': '30313436-3631-5A43-3333-343252595448', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.105', 'portmap': {'mezz': [{'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 8}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 8}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 8}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 8}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 8}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 8}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'F0:92:1C:02:53:F8', 'type': 'C'}, {'function': 98, 'guid_string': 'F0:92:1C:02:53:F9', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:F0:92:1C:02:53:F9', 'type': 'G'}], 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'F0:92:1C:02:53:F8'}, {'guids': [{'function': 97, 'guid_string': 'F0:92:1C:02:53:FC', 'type': 'C'}, {'function': 98, 'guid_string': 'F0:92:1C:02:53:FD', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:F0:92:1C:02:53:FD', 'type': 'G'}], 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'F0:92:1C:02:53:FC'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 8}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 8}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 286, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL460c Gen8', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 40, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 45, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '641016CZ3342RYTH', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 11}, 'bsn': 'CZ3238WPVP', 'conjoinable': False, 'cuuid': '37333036-3831-5A43-3332-333857505650', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.106', 'portmap': {'mezz': [{'device': {'name': 'QLogic QMH2462 4Gb FC HBA for HP c-Class BladeSystem', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:03:be:4f:58'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:03:be:4f:5a'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 11}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 11}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'device': {'name': 'QLogic QMH2462 4Gb FC HBA for HP c-Class BladeSystem', 'port': [{'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:03:be:4b:4c'}, {'number': 2, 'status': 'UNKNOWN', 'type': 'INTERCONNECT_TYPE_FIB', 'wwpn': '50:01:43:80:03:be:4b:4e'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_ONE'}, 'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 11}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 11}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 11}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 11}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'B4:B5:2F:56:C2:50', 'type': 'C'}, {'function': 98, 'guid_string': 'B4:B5:2F:56:C2:51', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:B4:B5:2F:56:C2:51', 'type': 'G'}], 'iscsi': 'B4:B5:2F:56:C2:51', 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'B4:B5:2F:56:C2:50'}, {'guids': [{'function': 97, 'guid_string': 'B4:B5:2F:56:C2:54', 'type': 'C'}, {'function': 98, 'guid_string': 'B4:B5:2F:56:C2:55', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:B4:B5:2F:56:C2:55', 'type': 'G'}], 'iscsi': 'B4:B5:2F:56:C2:55', 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'B4:B5:2F:56:C2:54'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 11}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 11}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 232, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL460c G7', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 42, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 46, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '603718CZ3238WPVP', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 12}, 'bsn': 'CZ3404YWCE', 'conjoinable': False, 'cuuid': '30313436-3631-5A43-3334-303459574345', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.107', 'portmap': {'mezz': [{'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 12}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 12}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 12}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 12}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 12}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 12}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': '9C:B6:54:86:D9:D0', 'type': 'C'}, {'function': 98, 'guid_string': '9C:B6:54:86:D9:D1', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:9C:B6:54:86:D9:D1', 'type': 'G'}], 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': '9C:B6:54:86:D9:D0'}, {'guids': [{'function': 97, 'guid_string': '9C:B6:54:86:D9:D4', 'type': 'C'}, {'function': 98, 'guid_string': '9C:B6:54:86:D9:D5', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:9C:B6:54:86:D9:D5', 'type': 'G'}], 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': '9C:B6:54:86:D9:D4'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 12}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 12}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 284, 'powermode': 'UNKNOWN', 'powerstate': 'ON'}, 'spn': 'ProLiant BL460c Gen8', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '641016CZ3404YWCE', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}, {'associatedblade': 0, 'bay': {'connection': 15}, 'bsn': 'CZ34154488', 'conjoinable': False, 'cuuid': '30313436-3631-5A43-3334-313534343838', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NO_ERROR', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_TESTED', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NOT_TESTED', 'thermalwarning': 'NOT_TESTED'}, 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.108', 'portmap': {'mezz': [{'number': 1, 'slot': {'port': [{'number': 1, 'traybaynumber': 3, 'trayportnumber': 15}, {'number': 2, 'traybaynumber': 4, 'trayportnumber': 15}], 'type': 'MEZZ_SLOT_TYPE_ONE'}}, {'number': 2, 'slot': {'port': [{'number': 1, 'traybaynumber': 5, 'trayportnumber': 15}, {'number': 2, 'traybaynumber': 6, 'trayportnumber': 15}, {'number': 3, 'traybaynumber': 7, 'trayportnumber': 15}, {'number': 4, 'traybaynumber': 8, 'trayportnumber': 15}], 'type': 'MEZZ_SLOT_TYPE_TWO'}}, {'device': {'name': 'FlexFabric Embedded Ethernet', 'port': [{'guids': [{'function': 97, 'guid_string': 'FC:15:B4:0A:8D:A0', 'type': 'C'}, {'function': 98, 'guid_string': 'FC:15:B4:0A:8D:A1', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:FC:15:B4:0A:8D:A1', 'type': 'G'}], 'number': 1, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'FC:15:B4:0A:8D:A0'}, {'guids': [{'function': 97, 'guid_string': 'FC:15:B4:0A:8D:A4', 'type': 'C'}, {'function': 98, 'guid_string': 'FC:15:B4:0A:8D:A5', 'type': 'H'}, {'function': 98, 'guid_string': '10:00:FC:15:B4:0A:8D:A5', 'type': 'G'}], 'number': 2, 'status': 'OK', 'type': 'INTERCONNECT_TYPE_ETH', 'wwpn': 'FC:15:B4:0A:8D:A4'}], 'status': 'OK', 'type': 'MEZZ_DEV_TYPE_FIXED'}, 'number': 9, 'slot': {'port': [{'number': 1, 'traybaynumber': 1, 'trayportnumber': 15}, {'number': 2, 'traybaynumber': 2, 'trayportnumber': 15}], 'type': 'MEZZ_SLOT_TYPE_FIXED'}}], 'status': 'OK'}, 'power': {'power_consumed': 0, 'powermode': 'UNKNOWN', 'powerstate': 'OFF'}, 'spn': 'ProLiant BL460c Gen8', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '14', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'type': 'SERVER', 'uidstatus': 'OFF', 'uuid': '641016CZ34154488', 'vmstat': {'cdromstat': 'VM_DEV_STATUS_DISCONNECTED', 'cdromurl': None, 'floppystat': 'VM_DEV_STATUS_DISCONNECTED', 'floppyurl': None, 'support': 'VM_SUPPORTED'}}]}, 'datetime': '2015-04-08T18:22:02-05:00', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NOT_TESTED', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NOT_RELEVANT', 'oaredundancy': 'NO_ERROR', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'dim': {'mmdepth': 756, 'mmheight': 445, 'mmwidth': 444}, 'encl': 'OA-002655FF2F7B', 'encl_sn': 'GB8004HPR0', 'fans': {'bays': [{'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 20, 'mmyoffset': 0, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 98, 'mmyoffset': 0, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 176, 'mmyoffset': 0, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 254, 'mmyoffset': 0, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 332, 'mmyoffset': 0, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 20, 'mmyoffset': 261, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 98, 'mmyoffset': 261, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 176, 'mmyoffset': 261, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 254, 'mmyoffset': 261, 'side': 'REAR'}, {'mmdepth': 194, 'mmheight': 93, 'mmwidth': 78, 'mmxoffset': 332, 'mmyoffset': 261, 'side': 'REAR'}], 'fans': [{'bay': {'connection': 1}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 10, 'rpm_cur': 6350, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 2}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 10, 'rpm_cur': 6350, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 3}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 20, 'rpm_cur': 8399, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 4}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 18, 'rpm_cur': 8400, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 5}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 20, 'rpm_cur': 8400, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 6}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 11, 'rpm_cur': 6350, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 7}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 9, 'rpm_cur': 6350, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 8}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 10, 'rpm_cur': 6440, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 9}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 11, 'rpm_cur': 6440, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}, {'bay': {'connection': 10}, 'pn': '412140-B21', 'productname': 'Active Cool 200 Fan', 'pwr_used': 9, 'rpm_cur': 6442, 'rpm_max': 18000, 'rpm_min': 10, 'status': 'OK'}], 'needed_fans': '9', 'redundancy': 'REDUNDANT', 'status': 'OK', 'wanted_fans': '10'}, 'lcds': {'bays': [{'mmdepth': 15, 'mmheight': 55, 'mmwidth': 92, 'mmxoffset': 145, 'mmyoffset': 365, 'side': 'FRONT'}], 'lcds': [{'bay': {'connection': 1}, 'button_lock_enabled': False, 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NOT_TESTED', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NOT_RELEVANT', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '2.4.3', 'image_url': '/cgi-bin/getLCDImage?oaSessionKey=', 'manufacturer': 'HP', 'pin_enabled': False, 'pn': '441203-001', 'spn': 'BladeSystem c7000 Insight Display', 'status': 'OK', 'usernotes': 'Upload up to^six lines of^text information and your^320x240 bitmap using the^Onboard Administrator^web user interface'}]}, 'managers': {'bays': [{'mmdepth': 177, 'mmheight': 21, 'mmwidth': 160, 'mmxoffset': 0, 'mmyoffset': 225, 'side': 'REAR'}, {'mmdepth': 177, 'mmheight': 21, 'mmwidth': 160, 'mmxoffset': 255, 'mmyoffset': 225, 'side': 'REAR'}], 'managers': [{'bay': {'connection': 1}, 'bsn': 'OB99BP0372', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NOT_TESTED', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NOT_TESTED', 'oaredundancy': 'NOT_TESTED', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '3.32', 'ipv6status': 'DISABLED', 'macaddr': '00:26:55:FF:2F:7B', 'manufacturer': 'HP', 'mgmtipaddr': '10.42.128.109', 'name': 'OA-002655FF2F7B', 'power': {'powerstate': 'ON'}, 'role': 'ACTIVE', 'spn': 'BladeSystem c7000 DDR2 Onboard Administrator with KVM', 'status': 'OK', 'temps': {'c': '29', 'desc': 'AMBIENT', 'location': '17', 'thresholds': [{'c': 75, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 80, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'uidstatus': 'OFF', 'uuid': '09OB99BP0372', 'wizardstatus': 'WIZARD_SETUP_COMPLETE', 'youarehere': True}, {'bay': {'connection': 2}, 'bsn': 'OB9CBP3658', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NOT_TESTED', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NOT_TESTED', 'oaredundancy': 'NOT_TESTED', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '3.32', 'ipv6status': 'DISABLED', 'macaddr': 'F4:CE:46:BD:CA:8B', 'manufacturer': 'HP', 'mgmtipaddr': '0.0.0.0', 'name': 'OA-F4CE46BDCA8B', 'power': {'powerstate': 'ON'}, 'role': 'STANDBY', 'spn': 'BladeSystem c7000 DDR2 Onboard Administrator with KVM', 'status': 'OK', 'temps': {'c': '29', 'desc': 'AMBIENT', 'location': '17', 'thresholds': [{'c': 75, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 80, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'uidstatus': 'OFF', 'uuid': '09OB9CBP3658', 'wizardstatus': 'WIZARD_SETUP_COMPLETE', 'youarehere': False}]}, 'part': '507019-B21', 'pn': 'BladeSystem c7000 Enclosure G2', 'power': {'bays': [{'mmdepth': 700, 'mmheight': 56, 'mmwidth': 70, 'mmxoffset': 0, 'mmyoffset': 365, 'side': 'FRONT'}, {'mmdepth': 700, 'mmheight': 56, 'mmwidth': 70, 'mmxoffset': 70, 'mmyoffset': 365, 'side': 'FRONT'}, {'mmdepth': 700, 'mmheight': 56, 'mmwidth': 70, 'mmxoffset': 140, 'mmyoffset': 365, 'side': 'FRONT'}, {'mmdepth': 700, 'mmheight': 56, 'mmwidth': 70, 'mmxoffset': 210, 'mmyoffset': 365, 'side': 'FRONT'}, {'mmdepth': 700, 'mmheight': 56, 'mmwidth': 70, 'mmxoffset': 280, 'mmyoffset': 365, 'side': 'FRONT'}, {'mmdepth': 700, 'mmheight': 56, 'mmwidth': 70, 'mmxoffset': 350, 'mmyoffset': 365, 'side': 'FRONT'}], 'capacity': '4800', 'dynamicpowersaver': 'false', 'needed_ps': '2', 'output_power': '8028', 'pdu': '413374-B21', 'power_consumed': '4580', 'poweronflag': 'false', 'powersupply': [{'acinput': 'OK', 'actualoutput': 387, 'bay': {'connection': 1}, 'capacity': 2400, 'diag': {'ac': 'NO_ERROR', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_TESTED', 'mgmtproc': 'NOT_RELEVANT', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '0.00', 'pn': '499253-B21', 'sn': '5AGUD0AHLYA46R', 'status': 'OK'}, {'acinput': 'OK', 'actualoutput': 387, 'bay': {'connection': 2}, 'capacity': 2400, 'diag': {'ac': 'NO_ERROR', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_TESTED', 'mgmtproc': 'NOT_RELEVANT', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '0.00', 'pn': '499253-B21', 'sn': '5AGUD0AHLYA472', 'status': 'OK'}, {'acinput': 'OK', 'actualoutput': 387, 'bay': {'connection': 5}, 'capacity': 2400, 'diag': {'ac': 'NO_ERROR', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_TESTED', 'mgmtproc': 'NOT_RELEVANT', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '0.00', 'pn': '499253-B21', 'sn': '5AGUD0AHLYA46W', 'status': 'OK'}, {'acinput': 'OK', 'actualoutput': 387, 'bay': {'connection': 6}, 'capacity': 2400, 'diag': {'ac': 'NO_ERROR', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NOT_RELEVANT', 'location': 'NOT_TESTED', 'mgmtproc': 'NOT_RELEVANT', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NOT_RELEVANT', 'thermaldanger': 'NOT_RELEVANT', 'thermalwarning': 'NOT_RELEVANT'}, 'fwri': '0.00', 'pn': '499253-B21', 'sn': '5AGUD0AHLYA474', 'status': 'OK'}], 'redundancy': 'REDUNDANT', 'redundancymode': 'AC_REDUNDANT', 'redundant_capacity': '220', 'status': 'OK', 'type': 'INTERNAL_DC', 'wanted_ps': '4'}, 'rack': 'UnnamedRack', 'solutionsid': 0, 'status': 'OK', 'switches': {'bays': [{'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 0, 'mmyoffset': 95, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 193, 'mmyoffset': 95, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 0, 'mmyoffset': 123, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 193, 'mmyoffset': 123, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 0, 'mmyoffset': 151, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 193, 'mmyoffset': 151, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 0, 'mmyoffset': 179, 'side': 'REAR'}, {'mmdepth': 268, 'mmheight': 28, 'mmwidth': 193, 'mmxoffset': 193, 'mmyoffset': 179, 'side': 'REAR'}], 'switches': [{'bay': {'connection': 1}, 'bsn': 'TWT952V0GZ', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NO_ERROR', 'thermalwarning': 'NO_ERROR'}, 'fabrictype': 'INTERCONNECT_TYPE_ETH', 'manufacturer': 'HP', 'mgmtipaddr': '0.0.0.0', 'mgmturl': None, 'portmap': {'passthru_mode_enabled': 'ENABLED', 'slot': {'port': [{'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 1, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 9, 'blademezzportnumber': 3, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 2, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 3, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 3, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 4, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 4, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 5, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 9, 'blademezzportnumber': 3, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 6, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 7, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 7, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 8, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 8, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 9, 'blademezzportnumber': 5, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 9, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 10, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 11, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 11, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 12, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 12, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 9, 'blademezzportnumber': 5, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 13, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 14, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 15, 'blademezznumber': 9, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 15, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 16, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}], 'type': 'INTERCONNECT_TYPE_ETH'}, 'status': 'OK'}, 'power': {'power_off_wattage': 3, 'power_on_wattage': 32, 'powerstate': 'ON'}, 'spn': 'HP 1Gb Ethernet Pass-Thru Module for c-Class BladeSystem', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '13', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'thermal': 'OK', 'uidstatus': 'OFF'}, {'bay': {'connection': 2}, 'bsn': 'TWT952V0DM', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NO_ERROR', 'failure': 'NO_ERROR', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NO_ERROR', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NO_ERROR', 'thermalwarning': 'NO_ERROR'}, 'fabrictype': 'INTERCONNECT_TYPE_ETH', 'manufacturer': 'HP', 'mgmtipaddr': '0.0.0.0', 'mgmturl': None, 'portmap': {'passthru_mode_enabled': 'ENABLED', 'slot': {'port': [{'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 1, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 9, 'blademezzportnumber': 4, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 2, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 3, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 3, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 4, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 4, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 5, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 9, 'blademezzportnumber': 4, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 6, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 7, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 7, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 8, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 8, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 9, 'blademezzportnumber': 6, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 9, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 10, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 11, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 11, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 12, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 12, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 9, 'blademezzportnumber': 6, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 13, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 14, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 15, 'blademezznumber': 9, 'blademezzportnumber': 2, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 15, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 16, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}], 'type': 'INTERCONNECT_TYPE_ETH'}, 'status': 'OK'}, 'power': {'power_off_wattage': 3, 'power_on_wattage': 32, 'powerstate': 'ON'}, 'spn': 'HP 1Gb Ethernet Pass-Thru Module for c-Class BladeSystem', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '13', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'thermal': 'OK', 'uidstatus': 'OFF'}, {'bay': {'connection': 3}, 'bsn': 'TWT805V086', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NOT_TESTED', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NOT_TESTED', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NO_ERROR', 'thermalwarning': 'NO_ERROR'}, 'fabrictype': 'INTERCONNECT_TYPE_FIB', 'fault': 'CPUFAULT', 'manufacturer': 'HP', 'mgmtipaddr': '0.0.0.0', 'mgmturl': None, 'portmap': {'passthru_mode_enabled': 'ENABLED', 'slot': {'port': [{'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 1, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 1, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 2, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 3, 'blademezznumber': 1, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 3, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 4, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 5, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 1, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 6, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 7, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 8, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 9, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 10, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 11, 'blademezznumber': 1, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 11, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 12, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 13, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 14, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 15, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 16, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}], 'type': 'INTERCONNECT_TYPE_FIB'}, 'status': 'OK'}, 'power': {'power_off_wattage': 3, 'power_on_wattage': 32, 'powerstate': 'ON'}, 'spn': 'HP 4Gb Fibre Channel Pass-thru Module for c-Class BladeSystem', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '13', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'thermal': 'OK', 'uidstatus': 'OFF'}, {'bay': {'connection': 5}, 'bsn': 'TWT804V0UF', 'diag': {'ac': 'NOT_RELEVANT', 'cooling': 'NOT_RELEVANT', 'degraded': 'NOT_TESTED', 'failure': 'NOT_TESTED', 'fru': 'NO_ERROR', 'i2c': 'NOT_RELEVANT', 'keying': 'NO_ERROR', 'location': 'NOT_RELEVANT', 'mgmtproc': 'NOT_TESTED', 'oaredundancy': 'NOT_RELEVANT', 'power': 'NO_ERROR', 'thermaldanger': 'NO_ERROR', 'thermalwarning': 'NO_ERROR'}, 'fabrictype': 'INTERCONNECT_TYPE_FIB', 'fault': 'CPUFAULT', 'manufacturer': 'HP', 'mgmtipaddr': '0.0.0.0', 'mgmturl': None, 'portmap': {'passthru_mode_enabled': 'ENABLED', 'slot': {'port': [{'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 1, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 2, 'blademezznumber': 2, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 2, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 3, 'blademezznumber': 2, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 3, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 4, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 5, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 6, 'blademezznumber': 2, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 6, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 7, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 8, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 9, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 10, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 11, 'blademezznumber': 2, 'blademezzportnumber': 1, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 11, 'status': 'OK', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 12, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 13, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 14, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 15, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}, {'bladebaynumber': 0, 'blademezznumber': 0, 'blademezzportnumber': 0, 'enabled': 'UNKNOWN', 'link_led_status': 'UNKNOWN', 'number': 16, 'status': 'UNKNOWN', 'uid_status': 'UNKNOWN'}], 'type': 'INTERCONNECT_TYPE_FIB'}, 'status': 'OK'}, 'power': {'power_off_wattage': 3, 'power_on_wattage': 32, 'powerstate': 'ON'}, 'spn': 'HP 4Gb Fibre Channel Pass-thru Module for c-Class BladeSystem', 'status': 'OK', 'temps': {'c': '0', 'desc': 'AMBIENT', 'location': '13', 'thresholds': [{'c': 0, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 0, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'thermal': 'OK', 'uidstatus': 'OFF'}]}, 'temps': {'c': '29', 'desc': 'AMBIENT', 'location': '9', 'thresholds': [{'c': 75, 'desc': 'CAUTION', 'status': 'Degraded'}, {'c': 80, 'desc': 'CRITICAL', 'status': 'Non-Recoverable Error'}]}, 'timezone': 'CST6CDT', 'uidstatus': 'OFF', 'uuid': '09GB8004HPR0', 'vcm': {'vcmdomainid': None, 'vcmdomainname': None, 'vcmmode': False, 'vcmurl': 'empty'}, 'vm': {'dvddrive': 'ABSENT'}}, 'mp': {'cimom': False, 'fwri': '3.32', 'hwri': '65.51', 'pn': 'BladeSystem c7000 DDR2 Onboard Administrator with KVM', 'prim': True, 'sn': 'OB99BP0372', 'sso': False, 'st': 1, 'ste': False, 'useste': False, 'uuid': '09OB99BP0372'}, 'rk_tplgy': {'icmb': {'addr': 'A9FE0106', 'mfg': 232, 'prod_id': '0x0009', 'ser': 'GB8004HPR0', 'uuid': '09GB8004HPR0'}, 'ruid': '09GB8004HPR0'}} python-hpilo-3.6/docs/output/get_embedded_health0000644000175000017500000007761312652734620022753 0ustar dennisdennis00000000000000{'fans': {'Virtual Fan': {'label': 'Virtual Fan', 'speed': (22, 'Percentage'), 'status': 'OK', 'zone': 'Virtual'}}, 'firmware_information': {'HP ProLiant System ROM': '08/02/2014', 'HP ProLiant System ROM - Backup': '12/20/2013', 'HP ProLiant System ROM Bootblock': '03/05/2013', 'Power Management Controller Firmware': '3.3', 'Power Management Controller Firmware Bootloader': '2.7', 'Server Platform Services (SPS) Firmware': '2.1.7.E7.4', 'System Programmable Logic Device': 'Version 0x13', 'iLO': '1.51 Jun 16 2014'}, 'health_at_a_glance': {'bios_hardware': {'status': 'OK'}, 'fans': {'status': 'OK'}, 'memory': {'status': 'OK'}, 'network': {'status': 'OK'}, 'processor': {'status': 'OK'}, 'storage': {'status': 'OK'}, 'temperature': {'status': 'OK'}}, 'memory': {'advanced_memory_protection': {'amp_mode_status': 'Advanced ECC', 'available_amp_modes': 'On-line Spare, Advanced ECC', 'configured_amp_mode': 'Advanced ECC'}, 'memory_details': {'CPU_1': {'socket 1': {'frequency': '1600 MHz', 'hp_smart_memory': 'Yes', 'minimum_voltage': '1.50 v', 'part': {'number': '672612-081'}, 'ranks': 2, 'size': '16384 MB', 'socket': 1, 'status': 'Good, In Use', 'technology': 'RDIMM', 'type': 'DIMM DDR3'}, 'socket 2': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 2, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 3': {'frequency': '1600 MHz', 'hp_smart_memory': 'Yes', 'minimum_voltage': '1.50 v', 'part': {'number': '672612-081'}, 'ranks': 2, 'size': '16384 MB', 'socket': 3, 'status': 'Good, In Use', 'technology': 'RDIMM', 'type': 'DIMM DDR3'}, 'socket 4': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 4, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 5': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 5, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 6': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 6, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 7': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 7, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 8': {'frequency': '1600 MHz', 'hp_smart_memory': 'Yes', 'minimum_voltage': '1.50 v', 'part': {'number': '672612-081'}, 'ranks': 2, 'size': '16384 MB', 'socket': 8, 'status': 'Good, In Use', 'technology': 'RDIMM', 'type': 'DIMM DDR3'}}, 'CPU_2': {'socket 1': {'frequency': '1600 MHz', 'hp_smart_memory': 'Yes', 'minimum_voltage': '1.50 v', 'part': {'number': '672612-081'}, 'ranks': 2, 'size': '16384 MB', 'socket': 1, 'status': 'Good, In Use', 'technology': 'RDIMM', 'type': 'DIMM DDR3'}, 'socket 2': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 2, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 3': {'frequency': '1600 MHz', 'hp_smart_memory': 'Yes', 'minimum_voltage': '1.50 v', 'part': {'number': '672612-081'}, 'ranks': 2, 'size': '16384 MB', 'socket': 3, 'status': 'Good, In Use', 'technology': 'RDIMM', 'type': 'DIMM DDR3'}, 'socket 4': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 4, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 5': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 5, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 6': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 6, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 7': {'frequency': 'N/A', 'hp_smart_memory': 'N/A', 'minimum_voltage': 'N/A', 'part': {'number': 'N/A'}, 'ranks': 'N/A', 'size': 'N/A', 'socket': 7, 'status': 'Not Present', 'technology': 'N/A', 'type': 'N/A'}, 'socket 8': {'frequency': '1600 MHz', 'hp_smart_memory': 'Yes', 'minimum_voltage': '1.50 v', 'part': {'number': '672612-081'}, 'ranks': 2, 'size': '16384 MB', 'socket': 8, 'status': 'Good, In Use', 'technology': 'RDIMM', 'type': 'DIMM DDR3'}}}, 'memory_details_summary': {'cpu_1': {'number_of_sockets': 8, 'operating_frequency': '1333 MHz', 'operating_voltage': '1.50 v', 'total_memory_size': '48 GB'}, 'cpu_2': {'number_of_sockets': 8, 'operating_frequency': '1333 MHz', 'operating_voltage': '1.50 v', 'total_memory_size': '48 GB'}}}, 'nic_information': {'NIC Port 1': {'ip_address': 'N/A', 'location': 'Embedded', 'mac_address': 'fc:15:b4:0a:9d:58', 'network_port': 'Port 1', 'port_description': 'N/A', 'status': 'Unknown'}, 'NIC Port 2': {'ip_address': 'N/A', 'location': 'Embedded', 'mac_address': 'fc:15:b4:0a:9d:5c', 'network_port': 'Port 2', 'port_description': 'N/A', 'status': 'Unknown'}, 'iLO iLO Dedicated Network Port': {'ip_address': '10.42.128.1', 'location': 'Embedded', 'mac_address': '9c:b6:54:8e:4b:7c', 'network_port': 'iLO Dedicated Network Port', 'port_description': 'iLO Dedicated Network Port', 'status': 'OK'}}, 'power_supplies': {}, 'power_supply_summary': {'power_management_controller_firmware_version': '3.3', 'present_power_reading': '65 Watts'}, 'processors': {'Proc 1': {'execution_technology': '6/6 cores; 12 threads', 'internal_l1_cache': '192 KB', 'internal_l2_cache': '1536 KB', 'internal_l3_cache': '15360 KB', 'label': 'Proc 1', 'memory_technology': '64-bit Capable', 'name': ' Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz ', 'speed': '2500 MHz', 'status': 'OK'}, 'Proc 2': {'execution_technology': '6/6 cores; 12 threads', 'internal_l1_cache': '192 KB', 'internal_l2_cache': '1536 KB', 'internal_l3_cache': '15360 KB', 'label': 'Proc 2', 'memory_technology': '64-bit Capable', 'name': ' Intel(R) Xeon(R) CPU E5-2640 0 @ 2.50GHz ', 'speed': '2500 MHz', 'status': 'OK'}}, 'storage': {'Controller on System Board': {'cache_module_memory': '524288 KB', 'cache_module_serial_num': 'PBKHV', 'cache_module_status': 'OK', 'controller_status': 'OK', 'drive_enclosures': [{'drive_bay': 2, 'label': 'Port 1I Box 1', 'status': 'OK'}], 'fw_version': '5.42', 'label': 'Controller on System Board', 'logical_drives': [{'capacity': '558 GB', 'encryption_status': 'Not Encrypted', 'fault_tolerance': 'RAID 1/RAID 1+0', 'label': '01', 'physical_drives': [{'capacity': '558 GB', 'drive_configuration': 'Configured', 'encryption_status': 'Not Encrypted', 'fw_version': 'HPD5', 'label': 'Port 1I Box 1 Bay 1', 'location': 'Port 1I Box 1 Bay 1', 'model': 'EG0600FCVBK', 'serial_number': 'S0M243NV0000M433M04G', 'status': 'OK'}, {'capacity': '558 GB', 'drive_configuration': 'Configured', 'encryption_status': 'Not Encrypted', 'fw_version': 'HPD5', 'label': 'Port 1I Box 1 Bay 2', 'location': 'Port 1I Box 1 Bay 2', 'model': 'EG0600FCVBK', 'serial_number': 'S0M244080000M433FABZ', 'status': 'OK'}], 'status': 'OK'}], 'model': 'HP Smart Array P220i Controller', 'serial_number': 'PCQVU0CRH6D13P', 'status': 'OK'}}, 'temperature': {'01-Inlet Ambient': {'caution': (42, 'Celsius'), 'critical': (46, 'Celsius'), 'currentreading': (19, 'Celsius'), 'label': '01-Inlet Ambient', 'location': 'Ambient', 'status': 'OK'}, '02-CPU 1': {'caution': (70, 'Celsius'), 'critical': 'N/A', 'currentreading': (40, 'Celsius'), 'label': '02-CPU 1', 'location': 'CPU', 'status': 'OK'}, '03-CPU 2': {'caution': (70, 'Celsius'), 'critical': 'N/A', 'currentreading': (40, 'Celsius'), 'label': '03-CPU 2', 'location': 'CPU', 'status': 'OK'}, '04-P1 DIMM 1-4': {'caution': (87, 'Celsius'), 'critical': 'N/A', 'currentreading': (26, 'Celsius'), 'label': '04-P1 DIMM 1-4', 'location': 'Memory', 'status': 'OK'}, '05-P1 DIMM 5-8': {'caution': (87, 'Celsius'), 'critical': 'N/A', 'currentreading': (25, 'Celsius'), 'label': '05-P1 DIMM 5-8', 'location': 'Memory', 'status': 'OK'}, '06-P2 DIMM 1-4': {'caution': (87, 'Celsius'), 'critical': 'N/A', 'currentreading': (24, 'Celsius'), 'label': '06-P2 DIMM 1-4', 'location': 'Memory', 'status': 'OK'}, '07-P2 DIMM 5-8': {'caution': (87, 'Celsius'), 'critical': 'N/A', 'currentreading': (24, 'Celsius'), 'label': '07-P2 DIMM 5-8', 'location': 'Memory', 'status': 'OK'}, '08-P1 Mem Zone': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (29, 'Celsius'), 'label': '08-P1 Mem Zone', 'location': 'Memory', 'status': 'OK'}, '09-P1 Mem Zone': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (28, 'Celsius'), 'label': '09-P1 Mem Zone', 'location': 'Memory', 'status': 'OK'}, '10-P2 Mem Zone': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (25, 'Celsius'), 'label': '10-P2 Mem Zone', 'location': 'Memory', 'status': 'OK'}, '11-P2 Mem Zone': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (27, 'Celsius'), 'label': '11-P2 Mem Zone', 'location': 'Memory', 'status': 'OK'}, '12-HD Max': {'caution': (60, 'Celsius'), 'critical': 'N/A', 'currentreading': (35, 'Celsius'), 'label': '12-HD Max', 'location': 'System', 'status': 'OK'}, '13-Chipset': {'caution': (105, 'Celsius'), 'critical': 'N/A', 'currentreading': (44, 'Celsius'), 'label': '13-Chipset', 'location': 'System', 'status': 'OK'}, '14-Chipset Zone': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (32, 'Celsius'), 'label': '14-Chipset Zone', 'location': 'System', 'status': 'OK'}, '15-VR P1': {'caution': (115, 'Celsius'), 'critical': (120, 'Celsius'), 'currentreading': (33, 'Celsius'), 'label': '15-VR P1', 'location': 'System', 'status': 'OK'}, '16-VR P2': {'caution': (115, 'Celsius'), 'critical': (120, 'Celsius'), 'currentreading': (31, 'Celsius'), 'label': '16-VR P2', 'location': 'System', 'status': 'OK'}, '17-VR P1 Mem': {'caution': (115, 'Celsius'), 'critical': (120, 'Celsius'), 'currentreading': (32, 'Celsius'), 'label': '17-VR P1 Mem', 'location': 'System', 'status': 'OK'}, '18-VR P1 Mem': {'caution': (115, 'Celsius'), 'critical': (120, 'Celsius'), 'currentreading': (31, 'Celsius'), 'label': '18-VR P1 Mem', 'location': 'System', 'status': 'OK'}, '19-VR P2 Mem': {'caution': (115, 'Celsius'), 'critical': (120, 'Celsius'), 'currentreading': (26, 'Celsius'), 'label': '19-VR P2 Mem', 'location': 'System', 'status': 'OK'}, '20-VR P2 Mem': {'caution': (115, 'Celsius'), 'critical': (120, 'Celsius'), 'currentreading': (27, 'Celsius'), 'label': '20-VR P2 Mem', 'location': 'System', 'status': 'OK'}, '21-SuperCap Max': {'caution': (65, 'Celsius'), 'critical': 'N/A', 'currentreading': (19, 'Celsius'), 'label': '21-SuperCap Max', 'location': 'System', 'status': 'OK'}, '22-HD Controller': {'caution': (100, 'Celsius'), 'critical': 'N/A', 'currentreading': (46, 'Celsius'), 'label': '22-HD Controller', 'location': 'I/O Board', 'status': 'OK'}, '23-HDcntlr Inlet': {'caution': (70, 'Celsius'), 'critical': 'N/A', 'currentreading': (40, 'Celsius'), 'label': '23-HDcntlr Inlet', 'location': 'I/O Board', 'status': 'OK'}, '24-LOM Card': {'caution': (100, 'Celsius'), 'critical': 'N/A', 'currentreading': (40, 'Celsius'), 'label': '24-LOM Card', 'location': 'I/O Board', 'status': 'OK'}, '25-LOM Card Zn': {'caution': (75, 'Celsius'), 'critical': 'N/A', 'currentreading': (40, 'Celsius'), 'label': '25-LOM Card Zn', 'location': 'I/O Board', 'status': 'OK'}, '26-Mezz 1': {'caution': 'N/A', 'critical': 'N/A', 'currentreading': 'N/A', 'label': '26-Mezz 1', 'location': 'I/O Board', 'status': 'Not Installed'}, '27-Mezz 1 Inlet': {'caution': 'N/A', 'critical': 'N/A', 'currentreading': 'N/A', 'label': '27-Mezz 1 Inlet', 'location': 'I/O Board', 'status': 'Not Installed'}, '28-Mezz 2': {'caution': 'N/A', 'critical': 'N/A', 'currentreading': 'N/A', 'label': '28-Mezz 2', 'location': 'I/O Board', 'status': 'Not Installed'}, '29-Mezz 2 Inlet': {'caution': 'N/A', 'critical': 'N/A', 'currentreading': 'N/A', 'label': '29-Mezz 2 Inlet', 'location': 'I/O Board', 'status': 'Not Installed'}, '30-System Board': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (30, 'Celsius'), 'label': '30-System Board', 'location': 'System', 'status': 'OK'}, '31-System Board': {'caution': (90, 'Celsius'), 'critical': (95, 'Celsius'), 'currentreading': (28, 'Celsius'), 'label': '31-System Board', 'location': 'System', 'status': 'OK'}, '32-Sys Exhaust': {'caution': (75, 'Celsius'), 'critical': (80, 'Celsius'), 'currentreading': (25, 'Celsius'), 'label': '32-Sys Exhaust', 'location': 'System', 'status': 'OK'}, '33-Sys Exhaust': {'caution': (75, 'Celsius'), 'critical': (80, 'Celsius'), 'currentreading': (32, 'Celsius'), 'label': '33-Sys Exhaust', 'location': 'System', 'status': 'OK'}, '34-GPU 1': {'caution': 'N/A', 'critical': 'N/A', 'currentreading': 'N/A', 'label': '34-GPU 1', 'location': 'I/O Board', 'status': 'Not Installed'}, '35-GPU 2': {'caution': 'N/A', 'critical': 'N/A', 'currentreading': 'N/A', 'label': '35-GPU 2', 'location': 'I/O Board', 'status': 'Not Installed'}}, 'vrm': None} python-hpilo-3.6/docs/output/get_host_power_status0000644000175000017500000000000312652734620023444 0ustar dennisdennis00000000000000ON python-hpilo-3.6/docs/output/get_dir_config0000644000175000017500000000161712652734620021767 0ustar dennisdennis00000000000000{'dir_authentication_enabled': False, 'dir_enable_grp_acct': False, 'dir_grpacct1_name': 'Administrators', 'dir_grpacct1_priv': '1,2,3,4,5,6', 'dir_grpacct1_sid': '', 'dir_grpacct2_name': 'Authenticated Users', 'dir_grpacct2_priv': 6, 'dir_grpacct2_sid': 'S-1-5-11', 'dir_kerberos_enabled': False, 'dir_kerberos_kdc_address': '', 'dir_kerberos_kdc_port': 88, 'dir_kerberos_realm': '', 'dir_local_user_acct': True, 'dir_object_dn': '', 'dir_server_address': '', 'dir_server_port': 636, 'dir_user_context_1': '', 'dir_user_context_10': '', 'dir_user_context_11': '', 'dir_user_context_12': '', 'dir_user_context_13': '', 'dir_user_context_14': '', 'dir_user_context_15': '', 'dir_user_context_2': '', 'dir_user_context_3': '', 'dir_user_context_4': '', 'dir_user_context_5': '', 'dir_user_context_6': '', 'dir_user_context_7': '', 'dir_user_context_8': '', 'dir_user_context_9': ''} python-hpilo-3.6/docs/output/get_server_auto_pwr0000644000175000017500000000000312652734620023076 0ustar dennisdennis00000000000000ON python-hpilo-3.6/docs/output/get_product_name0000644000175000017500000000002512652734620022334 0ustar dennisdennis00000000000000ProLiant BL460c Gen8 python-hpilo-3.6/docs/output/get_server_name0000644000175000017500000000004312652734620022162 0ustar dennisdennis00000000000000example-server.int.kaarsemaker.net python-hpilo-3.6/docs/output/get_tpm_status0000644000175000017500000000014712652734620022064 0ustar dennisdennis00000000000000>>> pprint(my_ilo.get_tpm_status()) {'tpm_enabled': 'No', 'tpm_present': 'No', 'tpm_supported': 'Yes'} python-hpilo-3.6/docs/output/get_ilo_event_log0000644000175000017500000000107212652734620022504 0ustar dennisdennis00000000000000[{'class': 'iLO 3', 'count': 1, 'description': 'Event log cleared.', 'initial_update': '01/30/2011 16:33', 'last_update': '01/30/2011 16:33', 'severity': 'Informational'}, {'class': 'iLO 3', 'count': 1, 'description': 'Server reset.', 'initial_update': '01/30/2011 16:34', 'last_update': '01/30/2011 16:34', 'severity': 'Caution'}, {'class': 'iLO 3', 'count': 4, 'description': 'Server power restored.', 'initial_update': '01/30/2011 16:34', 'last_update': '01/30/2011 16:42', 'severity': 'Informational'}, (Other log entries skipped)] python-hpilo-3.6/docs/output/get_host_data0000644000175000017500000001177712652734620021642 0ustar dennisdennis00000000000000[{'Date': '08/02/2014', 'Family': 'I31', 'b64_data': 'ABgAAAECAPADf4DayX0AAAAAAwf//wEzSFAASTMxADA4LzAyLzIwMTQAAA==', 'type': 0}, {'Product Name': 'ProLiant BL460c Gen8', 'Serial Number': 'CZ3415448C ', 'UUID': '641016CZ3415448C', 'b64_data': 'ARsAAQQFAAE2NDEwMTZDWjM0MTU0NDhDBgIDQ1ozNDE1NDQ4QyAgICAgIAA2NDEwMTYtQjIxICAgICAgAFByb0xpYW50AEhQAFByb0xpYW50IEJMNDYwYyBHZW44ACAgICAgICAgICAgICAASFAAUHJvTGlhbnQgV1M0NjBjIEdlbjggV1MgQmxhZGUAAA==', 'cUUID': '30313436-3631-5A43-3334-313534343843', 'type': 1}, {'Execution Technology': '6 of 6 cores; 12 threads', 'Label': 'Proc 1', 'Memory Technology': '64-bit Capable', 'Speed': '2500 MHz', 'b64_data': 'BCoABAEDswLXBgIA//vrvwOOZADAEsQJQSYQByAHMAcAAAAGBgwEALMAUHJvYyAxAEludGVsACBJbnRlbChSKSBYZW9uKFIpIENQVSBFNS0yNjQwIDAgQCAyLjUwR0h6ICAgICAgIAAA', 'type': 4}, {'Execution Technology': '6 of 6 cores; 12 threads', 'Label': 'Proc 2', 'Memory Technology': '64-bit Capable', 'Speed': '2500 MHz', 'b64_data': 'BCoBBAEDswLXBgIA//vrvwOOZADAEsQJRCYWByYHNgcAAAAGBgwEALMAUHJvYyAyAEludGVsACBJbnRlbChSKSBYZW9uKFIpIENQVSBFNS0yNjQwIDAgQCAyLjUwR0h6ICAgICAgIAAA', 'type': 4}, {'Label': 'PROC 1 DIMM 1 ', 'Size': '16384 MB', 'Speed': '1600 MHz', 'b64_data': 'ESgAEQAQ/v9IAEAAAEAJAAEAGIAgQAYCAAADAgAAAAA1BdwF3AXcBVBST0MgIDEgRElNTSAgMSAASFAgICAgIAA2NzI2MTItMDgxICAgICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 2 ', 'Size': 'not installed', 'b64_data': 'ESgBEQAQ/v9IAEAAAAAJAQEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDEgRElNTSAgMiAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 3 ', 'Size': '16384 MB', 'Speed': '1600 MHz', 'b64_data': 'ESgCEQAQ/v9IAEAAAEAJAgEAGIAgQAYCAAADAgAAAAA1BdwF3AXcBVBST0MgIDEgRElNTSAgMyAASFAgICAgIAA2NzI2MTItMDgxICAgICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 4 ', 'Size': 'not installed', 'b64_data': 'ESgDEQAQ/v9IAEAAAAAJAwEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDEgRElNTSAgNCAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 5 ', 'Size': 'not installed', 'b64_data': 'ESgEEQAQ/v9IAEAAAAAJBAEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDEgRElNTSAgNSAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 6 ', 'Size': 'not installed', 'b64_data': 'ESgFEQAQ/v9IAEAAAAAJBQEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDEgRElNTSAgNiAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 7 ', 'Size': 'not installed', 'b64_data': 'ESgGEQAQ/v9IAEAAAAAJBgEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDEgRElNTSAgNyAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 1 DIMM 8 ', 'Size': '16384 MB', 'Speed': '1600 MHz', 'b64_data': 'ESgHEQAQ/v9IAEAAAEAJBwEAGIAgQAYCAAADAgAAAAA1BdwF3AXcBVBST0MgIDEgRElNTSAgOCAASFAgICAgIAA2NzI2MTItMDgxICAgICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 1 ', 'Size': '16384 MB', 'Speed': '1600 MHz', 'b64_data': 'ESgIEQEQ/v9IAEAAAEAJCAEAGIAgQAYCAAADAgAAAAA1BdwF3AXcBVBST0MgIDIgRElNTSAgMSAASFAgICAgIAA2NzI2MTItMDgxICAgICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 2 ', 'Size': 'not installed', 'b64_data': 'ESgJEQEQ/v9IAEAAAAAJCQEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDIgRElNTSAgMiAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 3 ', 'Size': '16384 MB', 'Speed': '1600 MHz', 'b64_data': 'ESgKEQEQ/v9IAEAAAEAJCgEAGIAgQAYCAAADAgAAAAA1BdwF3AXcBVBST0MgIDIgRElNTSAgMyAASFAgICAgIAA2NzI2MTItMDgxICAgICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 4 ', 'Size': 'not installed', 'b64_data': 'ESgLEQEQ/v9IAEAAAAAJCwEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDIgRElNTSAgNCAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 5 ', 'Size': 'not installed', 'b64_data': 'ESgMEQEQ/v9IAEAAAAAJDAEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDIgRElNTSAgNSAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 6 ', 'Size': 'not installed', 'b64_data': 'ESgNEQEQ/v9IAEAAAAAJDQEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDIgRElNTSAgNiAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 7 ', 'Size': 'not installed', 'b64_data': 'ESgOEQEQ/v9IAEAAAAAJDgEAGIAAAAACAAADAAAAAAAAAAAAAAAAAFBST0MgIDIgRElNTSAgNyAAVU5LTk9XTgBOT1QgQVZBSUxBQkxFICAgICAgIAAA', 'type': 17}, {'Label': 'PROC 2 DIMM 8 ', 'Size': '16384 MB', 'Speed': '1600 MHz', 'b64_data': 'ESgPEQEQ/v9IAEAAAEAJDwEAGIAgQAYCAAADAgAAAAA1BdwF3AXcBVBST0MgIDIgRElNTSAgOCAASFAgICAgIAA2NzI2MTItMDgxICAgICAgICAgIAAA', 'type': 17}, {'b64_data': '0RQA0QAE/BW0Cp1YAQT8FbQKnVwAAA==', 'fields': [{'name': 'Port', 'value': 1}, {'name': 'MAC', 'value': 'FC-15-B4-0A-9D-58'}, {'name': 'Port', 'value': 2}, {'name': 'MAC', 'value': 'FC-15-B4-0A-9D-5C'}, {'name': 'Port', 'value': 'iLO'}, {'name': 'MAC', 'value': '9C-B6-54-8E-4B-7C'}], 'type': 209}, {'Serial Number': 'CZ3415448C ', 'b64_data': '4hUA4jY0MTAxNkNaMzQxNTQ0OEMBQ1ozNDE1NDQ4QyAgICAgIAAA', 'cUUID': '30313436-3631-5A43-3334-313534343843', 'type': 226}] python-hpilo-3.6/docs/output/get_ers_settings0000644000175000017500000000053612652734620022374 0ustar dennisdennis00000000000000{'ers_agent': '', 'ers_collection_frequency': 'P30D', 'ers_connect_model': 0, 'ers_destination_port': 0, 'ers_destination_url': '', 'ers_last_transmission_date': '-', 'ers_last_transmission_errno': 'No error', 'ers_last_transmission_type': 0, 'ers_state': 0, 'ers_web_proxy_port': 0, 'ers_web_proxy_url': '', 'ers_web_proxy_username': ''} python-hpilo-3.6/docs/output/get_all_licenses0000644000175000017500000000024712652734620022317 0ustar dennisdennis00000000000000[{'license_class': 'FQL', 'license_install_date': 'Thu Mar 5 09:42:28 2015', 'license_key': 'ABCDE-FGHIJ-KLMNO-PQRST-UVXYZ', 'license_type': 'iLO 4 Advanced'}] python-hpilo-3.6/docs/output/get_host_pwr_micro_ver0000644000175000017500000000000412652734620023563 0ustar dennisdennis000000000000003.3 python-hpilo-3.6/docs/output/get_current_boot_mode0000644000175000017500000000000712652734620023365 0ustar dennisdennis00000000000000LEGACY python-hpilo-3.6/docs/output/get_server_power_on_time0000644000175000017500000000006512652734620024114 0ustar dennisdennis00000000000000>>> pprint(my_ilo.get_server_power_on_time()) 185813 python-hpilo-3.6/docs/output/get_security_msg0000644000175000017500000000013612652734620022374 0ustar dennisdennis00000000000000{'security_msg': 'Enabled', 'security_msg_text': 'Time is an illusion. Lunchtime doubly so'} python-hpilo-3.6/docs/output/get_fips_status0000644000175000017500000000003112652734620022215 0ustar dennisdennis00000000000000{'fips_mode': 'Enabled'} python-hpilo-3.6/docs/output/get_spatial0000644000175000017500000000062212652734620021314 0ustar dennisdennis00000000000000{'bay': 4, 'cuuid': '30313436-3631-5A43-3334-313534343843', 'discovery_data': 'Unknown data', 'discovery_rack': 'Not Supported', 'enclosure_cuuid': '42473930-3038-3430-4850-523000000000', 'enclosure_sn': 'GB8004HPR0', 'platform': 'BL', 'rack_description': 0, 'rack_id': 0, 'rack_id_pn': 0, 'rack_uheight': 0, 'tag_version': 0, 'uheight': 0, 'ulocation': 0, 'uoffset': 0, 'uposition': 0} python-hpilo-3.6/docs/output/get_oa_info0000644000175000017500000000025312652734620021271 0ustar dennisdennis00000000000000{'encl': 'chassis-25', 'ipaddress': '10.42.128.101', 'location': 1, 'macaddress': '68:b5:99:bb:dc:85', 'rack': 'chassis-25', 'system_health': 0, 'uidstatus': 'Off'} python-hpilo-3.6/docs/output/get_language0000644000175000017500000000005112652734620021436 0ustar dennisdennis00000000000000{'lang_id': 'en', 'language': 'English'} python-hpilo-3.6/docs/output/get_global_settings0000644000175000017500000000156512652734620023046 0ustar dennisdennis00000000000000{'alertmail_email_address': '', 'alertmail_enable': False, 'alertmail_sender_domain': '', 'alertmail_smtp_port': 25, 'alertmail_smtp_server': '', 'authentication_failure_logging': 'Enabled-every 3rd failure', 'enforce_aes': False, 'f8_login_required': False, 'f8_prompt_enabled': True, 'http_port': 80, 'https_port': 443, 'ipmi_dcmi_over_lan_enabled': True, 'lock_configuration': False, 'min_password': 8, 'propagate_time_to_host': True, 'rbsu_post_ip': True, 'remote_console_port': 23, 'remote_syslog_enable': True, 'remote_syslog_port': 514, 'remote_syslog_server_address': '10.42.128.3', 'serial_cli_speed': 9600, 'serial_cli_status': 'Enabled-Authentication Required', 'session_timeout': 30, 'snmp_access_enabled': True, 'snmp_port': 161, 'snmp_trap_port': 162, 'ssh_port': 22, 'ssh_status': True, 'virtual_media_port': 17988, 'vsp_log_enable': False} python-hpilo-3.6/docs/output/get_supported_boot_mode0000644000175000017500000000001412652734620023726 0ustar dennisdennis00000000000000LEGACY_ONLY python-hpilo-3.6/docs/output/get_pending_boot_mode0000644000175000017500000000000712652734620023327 0ustar dennisdennis00000000000000LEGACY python-hpilo-3.6/docs/output/get_host_power_saver_status0000644000175000017500000000003512652734620024651 0ustar dennisdennis00000000000000{'host_power_saver': 'AUTO'} python-hpilo-3.6/docs/output/get_one_time_boot0000644000175000017500000000000712652734620022476 0ustar dennisdennis00000000000000normal python-hpilo-3.6/docs/output/get_encrypt_settings0000644000175000017500000000051312652734620023262 0ustar dennisdennis00000000000000/home/dennis/code/python-hpilo/hpilo.py:533: IloWarning: ESKM servers are not configured. warnings.warn(child.get('MESSAGE'), IloWarning) {'enable_redundancy': True, 'eskm_cert_name': '', 'eskm_primary_server_address': '', 'eskm_primary_server_port': 0, 'eskm_secondary_server_address': '', 'eskm_secondary_server_port': 0} python-hpilo-3.6/docs/output/get_pers_mouse_keyboard_enabled0000644000175000017500000000000612652734620025366 0ustar dennisdennis00000000000000False python-hpilo-3.6/docs/output/get_snmp_im_settings0000644000175000017500000000142712652734620023245 0ustar dennisdennis00000000000000{'agentless_management_enable': True, 'cim_security_mask': 3, 'cold_start_trap_broadcast': True, 'os_traps': True, 'rib_traps': True, 'snmp_access': 'Enable', 'snmp_address_1': '', 'snmp_address_1_rocommunity': '', 'snmp_address_1_trapcommunity': '', 'snmp_address_2': '', 'snmp_address_2_rocommunity': '', 'snmp_address_2_trapcommunity': '', 'snmp_address_3': '', 'snmp_address_3_rocommunity': '', 'snmp_address_3_trapcommunity': '', 'snmp_passthrough_status': False, 'snmp_port': 161, 'snmp_sys_contact': '', 'snmp_sys_location': '', 'snmp_system_role': '', 'snmp_system_role_detail': '', 'snmp_trap_port': 162, 'snmp_v1_traps': True, 'snmp_v3_engine_id': '', 'trap_source_identifier': 'iLO Hostname', 'web_agent_ip_address': 'example-server.int.kaarsemaker.net'} python-hpilo-3.6/docs/output/get_all_users0000644000175000017500000000002212652734620021642 0ustar dennisdennis00000000000000['Administrator'] python-hpilo-3.6/docs/output/get_power_cap0000644000175000017500000000000412652734620021630 0ustar dennisdennis00000000000000OFF python-hpilo-3.6/docs/troubleshooting.rst0000644000175000017500000000734012652734620021522 0ustar dennisdennis00000000000000Common issues ============= The iLO interfaces aren't the most helpful when they detect something erroneous. These are some common issues and their solutions. If you have a problem that is not listed here, or solved with these instructions, please file an issue at https://github.com/seveas/python-hpilo. When reporting bugs, please do send the problematic XML responses. These XML responses can be saved as follows:: hpilo_cli example-server.int.kaarsemaker.net --save-response=for_bugreport.txt get_fw_version Of course you should replace the hostname with the actual iLO hostname or ip, and get_fw_version with the actual call you want to make. If you use the python API instead of the CLI tool, set the :data:`save_response` attribute on the ilo object:: ilo = hpilo.Ilo(hostname, login, password) ilo.save_response = "for_bugreport.txt" ilo.get_fw_version() These debug responses may contain sensitive information, which you should edit out. Please use a hexeditor to do so, or at least make sure your editor does not try to normalize newlines. It is important that the number of characters in the file stays the same, so don't add or remove data, just overwrite sensitive values with XXXX. As github issues do not support attachments, feel fee to mail this debug information to `the author`_ directly. .. _`the author`: mailto:dennis@kaarsemaker.net Update your firmware -------------------- This might sound like a lame cop-out, but quite a few versions of especially iLO 3 firmware contain serious bugs that cause the XML interface to misbehave. Upgrading the firmware of an iLO is simple and does not impact the host at all, so it's always a good idea to start with a firmware update:: hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware version=latest Syntax error: Line #0 --------------------- Occasionally you might see this error at the end of a traceback:: hpilo.IloError: Error communicating with iLO: Syntax error: Line #0: syntax error near "" in the line: "" This generaly means that you are trying to call a method that is not supported for your device or the firmware version you use. Get this information with:: hpilo_cli example-server.int.kaarsemaker.net get_fw_version And consult the HP sample XML files to find out whether this call is supported for your device and firmware version. If it is, please file a bug report. Note that for some calls (most notable mod_global_settings), support for the call may be there, but not all arguments are supported. ElementTree.ParseError ----------------------- Occasionally you might see either of these errors at the end of a traceback:: cElementTree.ParseError: not well-formed (invalid token): line 301, column 23 xml.etree.ElementTree.ParseError: not well-formed (invalid token): line 301, column 23 This means that the iLO interface is spewing invalid XML back at you. python-hpilo has some workarounds in place for common cases, and most other cases have been fixed in newer firmware versions. Please update your firmware version and try again. If the problem persists, please file a bug report. Unexpected errors after a login failure --------------------------------------- If you use the wrong credentials to access the XML interface, some iLO's get into some weird state. Call :func:`get_fw_version` a few times to clear this state and recover. Failure to update iLO3 firmware ------------------------------- The early firmware versions of iLO3 had quite a few issues. To update from anything older than 1.28 to 1.50 or newer, you need to update in two steps: first update to 1.28 and then update to a later version:: hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware version=1.28 hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware version=latest python-hpilo-3.6/docs/info.rst0000644000175000017500000000313212652734620017221 0ustar dennisdennis00000000000000General server and iLO information ================================== Many iLO methods allow you to retrieve information about the iLO and the server it is built into and to manipulate basic configuration settings. This document describes all the ones that do not fit under a more specific subject, such as authentication or power. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: factory_defaults .. automethod:: get_product_name .. ilo_output:: get_product_name .. automethod:: get_fw_version .. ilo_output:: get_fw_version .. automethod:: get_host_data .. ilo_output:: get_host_data .. automethod:: get_global_settings .. ilo_output:: get_global_settings .. automethod:: mod_global_settings .. automethod:: get_server_name .. ilo_output:: get_server_name .. automethod:: set_server_name .. automethod:: get_server_fqdn .. ilo_output:: get_server_fqdn .. automethod:: set_server_fqdn .. automethod:: get_smh_fqdn .. ilo_output:: get_smh_fqdn .. automethod:: get_oa_info .. ilo_output:: get_oa_info .. automethod:: get_asset_tag .. ilo_output:: get_asset_tag .. ilo_output:: get_asset_tag#1 .. automethod:: set_asset_tag .. automethod:: get_uid_status .. ilo_output:: get_uid_status .. automethod:: uid_control .. automethod:: get_all_languages .. ilo_output:: get_all_languages .. automethod:: get_language .. ilo_output:: get_language .. automethod:: set_language .. automethod:: get_rack_settings .. ilo_output:: get_rack_settings .. automethod:: get_spatial .. ilo_output:: get_spatial python-hpilo-3.6/docs/profile.rst0000644000175000017500000000065012652734620017730 0ustar dennisdennis00000000000000Deployment profiles =================== It is possible to automate iLO configurations with deployment profiles. With the following methods you can manage and apply such profiles. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: profile_desc_download .. automethod:: profile_list .. automethod:: profile_delete .. automethod:: profile_apply .. automethod:: profile_apply_get_results python-hpilo-3.6/docs/ahs.rst0000644000175000017500000000160712652734620017046 0ustar dennisdennis00000000000000Active Health System and Insight Remote Support =============================================== The Active Health System and Insight Remote Support functions let you collect information about your server environment in a central place. These functions let you inspect and manipulate the AHS and ERS configuration and submit data. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_ahs_status .. ilo_output:: get_ahs_status .. automethod:: set_ahs_status .. automethod:: ahs_clear_data .. automethod:: get_ers_settings .. ilo_output:: get_ers_settings .. automethod:: set_ers_irs_connect .. automethod:: set_ers_direct_connect .. automethod:: dc_registration_complete .. automethod:: set_ers_web_proxy .. automethod:: ers_ahs_submit .. automethod:: trigger_l2_collection .. automethod:: trigger_test_event .. automethod:: disable_ers python-hpilo-3.6/docs/ilodoc.py0000644000175000017500000000225012652734620017357 0ustar dennisdennis00000000000000from docutils.parsers.rst import Directive from docutils import nodes from sphinx.util.nodes import set_source_info import os import re import hpilo def setup(app): app.add_directive('ilo_output', OutputDirective) class OutputDirective(Directive): required_arguments = 1 optional_arguments = 0 def run(self): method = self.arguments[0] if '#' in method: method, suffix = method.split('#') suffix = '_' + suffix else: suffix = '' assert re.match('^[a-zA-Z][a-zA-Z0-9_]*$', method) srcdir = self.state.document.settings.env.srcdir with open(os.path.join(srcdir, 'output', method + suffix)) as fd: content = fd.read() if '\n\n' in content: params, result = content.split('\n\n') params = ', '.join(params.split('\n')) else: params, result = '', content out = ">>> ilo.%s(%s)\n%s" % (method, params, result) literal = nodes.literal_block(out, out) literal['language'] = 'python' set_source_info(self, literal) self.state.parent.children[-1].children[-1].append(literal) return [] python-hpilo-3.6/docs/federation.rst0000644000175000017500000000142412652734620020410 0ustar dennisdennis00000000000000Federation groups ================= iLO federation allows you to manage multiple iLOs and servers from a single iLO web interface, including firmware updates, license installs and querying health status. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: add_federation_group .. automethod:: get_federation_all_groups .. ilo_output:: get_federation_all_groups .. automethod:: get_federation_all_groups_info .. ilo_output:: get_federation_all_groups_info .. automethod:: get_federation_group .. ilo_output:: get_federation_group .. automethod:: mod_federation_group .. automethod:: delete_federation_group .. automethod:: get_federation_multicast .. ilo_output:: get_federation_multicast .. automethod:: set_federation_multicast python-hpilo-3.6/docs/python.rst0000644000175000017500000000720112652734620017610 0ustar dennisdennis00000000000000Access from Python ================== .. module:: hpilo The :py:mod:`hpilo` module contains all you need to communicate with iLO devices, encapsulated in the :class:`Ilo` class and its methods. There are a few auxiliarry items in this module too. .. py:class:: Ilo(hostname, login=None, password=None, timeout=60, port=443, protocol=None, delayed=False) Represents an iLO management interface on a specific host. :param hostname: Hostname or IP address of the iLO interface :param login: Loginname to use for authentication, not used for :py:data:`LOCAL` connections :param password: Password to use for authentication, not used for :py:data:`LOCAL` connections :param timeout: Timeout for creating connections or receiving data :param port: TCP port to use for HTTPS connections :param protocol: The protocol to use. Either :py:data:`hpilo.RAW` for remote iLO2 or older, :py:data:`hpilo.HTTP` for remote ilo3 and newer or :py:data:`hpilo.LOCAL` for using :program:`hponcfg` and the local kernel driver. If you do not specify this parameter, it will be autodetected. :param delayed: By default, this library will immediately contact the iLO for any method call you make and return a result. To save roundtrip time costs, set this to :py:data:`False` and call the :py:meth:`call_delayed` method manually. .. py:method:: call_delayed Calls all the delayed methods that have accumulated. This is best illustrated with an example. Observe the difference between: >>> ilo = hpilo.Ilo('example-server.int.kaarsemaker.net', 'Administrator', 'PassW0rd') >>> pprint(ilo.get_fw_version()) {'firmware_date': 'Aug 26 2011', 'firmware_version': '1.26', 'license_type': 'iLO 3 Advanced', 'management_processor': 'iLO3'} >>> pprint(ilo.get_uid_status()) 'OFF' and >>> ilo = hpilo.Ilo('example-server.int.kaarsemaker.net', 'Administrator', ... 'PassW0rd', delayed=True) >>> pprint(ilo.get_fw_version()) None >>> pprint(ilo.get_uid_status()) None >>> pprint(ilo.call_delayed()) [{'firmware_date': 'Aug 26 2011', 'firmware_version': '1.26', 'license_type': 'iLO 3 Advanced', 'management_processor': 'iLO3'}, 'OFF'] The second example only contacts the iLO twice, avoiding the overhead of one HTTP connection. As this overhead is quite significant, it makes sense to do this when you need to make more than one API call. All other methods of this class are API calls that mimic the methods available via XML. These are documented separately in further pages here and in the `ilo scripting guide`_ published by HP. .. py:class:: IloWarning A warning that is raised when the iLO returns warning messages in its XML output .. py:class:: IloError An exception that is raised when the iLO or python-hpilo indicates an error has occured while processing your API call. For example when calling a method not supported by an iLO, when using invalid parameters or when the iLO returns unexpected data. .. py:class:: IloCommunicationError Subclass of IloError that specifically indicates errors writing data to or reading data from the iLO. .. py:class:: IloLoginFailed Subclass of IloError that indicates that you used the wrong username or password. .. _`hp`: http://www.hp.com/go/ilo .. _`ilo scripting guide`: http://www.hp.com/support/ilo4_cli_gde_en python-hpilo-3.6/docs/firmware.rst0000644000175000017500000000774512652734620020120 0ustar dennisdennis00000000000000Dealing with iLO firmware updates ================================= One of the key features of python_hpilo is that it makes iLO firmware updates painless. It can download the firmware for you, or you can feed it the .bin or .scexe files HP ships. From the CLI ------------ The method to call is :func:`update_rib_firmware`. To tell it which firmware version to install, you can specify a version or a filename. To install the latest version, you can use :data:`latest` as version. Information about available version numbers can be found in `firmware.conf`_. Some example commands:: hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware version=1.28 hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware version=latest hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware filename=CP007684.scexe hpilo_cli example-server.int.kaarsemaker.net update_rib_firmware filename=ilo2_225.bin If you just want to download the firmware, you can make :data:`hpilo_cli` do that too:: hpilo_cli download_rib_firmware all # Download latest firmware for all iLO types hpilo_cli download_rib_firmware ilo4 # Download latest iLO 4 firmware hpilo_cli download_rib_firmware ilo4 1.50 # Download a specific firmware version hpilo_cli download_rib_firmware ilo4 all # Download all firmware versions for iLO 4 hpilo_cli download_rib_firmware all all # Download all firmware versions for all iLO types .. _`firmware.conf`: https://raw.githubusercontent.com/seveas/python-hpilo/master/firmware.conf Using the API ------------- As the CLI is merely a thin wrapper around the API, using the API is as expected:: ilo = hpilo.Ilo(hostname, login, password) ilo.update_rib_firmware(version='latest') But since firmware updates may take a while, the iLO can provide progress messages, which your code may in turn show to your users. To receive these progress message, pass a callable to the :func:`update_rib_firmware` function. It will be called with single-line messages about the progress of the firmware download, upload and flash processes. This example shows them to the user, constantly overwriting the previous message:: def print_progress(text): sys.stdout.write('\r\033[K' + text) sys.stdout.flush() ilo = hpilo.Ilo(hostname, login, password) ilo.update_rib_firmware(version='latest', progress=print_progress) print("") Of course the firmware downloader can be used from the API as well:: import hpilo_fw hpilo_fw.download('ilo4', path='/var/cache/ilo_fw/', progress=print_progress) hpilo_fw.download('ilo3 1.28', path='/var/cache/ilo_fw', progress=print_progress) Using a local firmware mirror ----------------------------- The firmware download functions connect to the internet to download firmware. While they can be made to use a proxy, using the standard :data:`https_proxy` and :data:`http_proxy` variables, it may be desirable to only download data from inside your network. To do this, you can set a variable in ilo.conf for the cli:: [firmware] mirror = http://buildserver.example.com/ilo-firmware/ Or if you use the API, configure the firmware downloader, both the downloader and the updater will then use your mirror:: import hpilo, hpilo_fw hpilo_fw.config(mirror='http://buildserver.example.com/ilo-firmware/') ilo = hpilo.Ilo(hostname, login, password) ilo.update_rib_firmware(version='latest', progress=print_progress) print("") hpilo_fw.download('ilo4', progress=print_progress) Your mirror should contain both :file:`firmware.conf`, and the :data:`.bin` files for all firmware versions you want to support. You can create (and auto-update via cron) such a mirror with a simple shellscript:: #!/bin/sh cd /var/www/html/ilo-firmware wget -q https://raw.githubusercontent.com/seveas/python-hpilo/master/firmware.conf hpilo_cli -c /dev/null download_rib_firmware all all This will download and extract the necessary files to :file:`/var/www/html/ilo-firmware`. python-hpilo-3.6/docs/puppet.rst0000644000175000017500000002234212652734620017607 0ustar dennisdennis00000000000000Managing iLO's with puppet ========================== Instead of writing your own code to manage iLO interfaces with python-hpilo, you can also use a puppet module. While it doesn't support all the functionality of hpilo.py or hpilo_cli, it does support the more common functions (and more can be added, just file a bug!) It uses the same network device management framework as the existing tools to manage cisco devices or F5 loadbalancers, so you don't need to install anything special on each server and no custom iLO code is required. To install the module, simply copy the `modules/ilo` directory into your puppet tree and follow the instructions below to create recipes. Caching ------- This module heavily caches iLO output, most for more than a day. The cache is invalidated if settings etc. are changed by this module, but if you make changes manually, you will need to remove the cached information yourself. The cache lives in the per-device directories in `/var/lib/puppet/devices`. Because of this caching, applying the catalog takes only a few seconds instead of several minutes if there are no changes. Configuring puppet ------------------ Please configure `hpilo_cli` itself first, including username and password. The puppet `ilo` module works by using this tool. Once it works for you, you can configure puppet. To use `puppet device` to manage iLO's, the iLO devices must be added to `/etc/puppet/device.conf` on the server you want to use for managing them. The ilo module can be used in two ways: to manage an iLO remotely via HTTP and to manage an iLO locally via hpilo. With the former you can manage many iLOs from a single server, with the latter you can manage iLOs that are not (yet) reachable via the network. To manage the local iLO, you can put something this in `device.conf`:: [server-001.ilo.kaarsemaker.net] type ilo url ilo://server-001.ilo.kaarsemaker.net Note that the scheme is `ilo://`, this makes the ilo module use `hpilo_cli` in local mode. You must still use the ilo's FQDN though, as each node needs a unique name in puppet. I personally prefer the network method and configuring DHCP properly so all iLOs are reachable via the network. For this, `device.conf` looks like the following:: [server-001.ilo.kaarsemaker.net] type ilo url http://server-001.ilo.kaarsemaker.net [server-002.ilo.kaarsemaker.net] type ilo url http://server-002.ilo.kaarsemaker.net [server-003.ilo.kaarsemaker.net] type ilo url http://server-003.ilo.kaarsemaker.net In fact, it's generated by the iLO module. The management server has this snippet in its recipe: .. code-block:: puppet class s_mgmt { class{'ilo::proxy': devices => [ "http://server-001.ilo.kaarsemaker.net", "http://server-002.ilo.kaarsemaker.net", "http://server-003.ilo.kaarsemaker.net", ] } } Of course you can generate this however you want. Facts ----- Several facts are available for use in your recipes. * `$devicetype` is set to `ilo` * `$users` contains a list of all users * `$firmware_version`, `$firmware_date`, `$management_processor`, and `$license_type` are set to what `get_fw_version` provides * `$oa_encl`, `$oa_rack`, `$oa_ipaddress`, `$oa_location`, `$oa_macaddress`, `$oa_uidstatus` and `$oa_system_health` are set to what `get_oa_info` provides. These are only available on blade servers. Managing users -------------- You can use this module to create, modify and delete users. Unfortunately the normal `user` type cannot be used, so there's a special `ilo_user` type. .. code-block:: puppet ilo_user { "Administrator": admin_priv => true; "jack": ensure => absent; "dkaarsemaker": ensure => present, display_name => 'Dennis Kaarsemaker', password_atcreate => 'P4ssw0rd', reset_server_priv => false; "linda": ensure => present, password => 'hunter2' display_name => 'Linda', admin_priv => false, config_ilo_priv => false, reset_server_priv => true; } These example users show the features of this type: * You can create (`ensure => present`) or delete (`ensure => absent`) users. * You can manage their permissions (`admin_priv`, `config_ilo_priv`, `remote_cons_priv`, `reset_server_priv` and `virtual_media_priv`) * You can manage display names and passwords. Note that for users you want this module to create, these are mandatory attributes. Because user passwords cannot be queried, this module has to check the password every time by doing an http request. This can take a while and goes against the aggressive caching. To prevent these constant checks, you can use the `password_atcreate` parameter instead of the `password` parameter. This is only used when creating the user and is not checked subsequently. Should you want to change the user's password you can temporarily also add a `password` parameter until all devices have been updated. Managing iLO firmware --------------------- The `ilo_firmware` type can be used to manage firmware on your iLOs. .. code-block:: puppet ilo_firmware { $management_processor: ensure => "latest", http_proxy => "http://webproxy:3128" } The name of the resource must be the same as the iLO type, you can use a fact to make sure it is. `ensure` accepts any version number or the string `latest`, which will always upgrade to the latest version. `http_proxy` is optional and can be used to specify a proxy via which to download the firmware config and firmware. Managing settings ----------------- This module also includes an `ilo_settings` type. This is a relatively thin wrapper around functions like `mod_global_settings` to configure any of the following settings: global (`mod_global_settings`), network (`mod_network_settings`), snmp (`mod_snmp_im_settings`) and directory authentication (`mod_dir_config`). As with the above types, an example should make it clear. .. code-block:: puppet ilo_settings { "global": settings => { "remote_console_port" => 23, "enforce_aes" => true, "f8_login_required" => true, }; "network": settings => { "prim_dns_server" => "10.42.1.31", "sec_dns_server" => "10.42.1.32", }; } As you can see, the individual settings are not all parameters, instead there's only one settings parameter. Any setting that is not managed by puppet is completely left alone by this module, there are no defaults. Installing licenses ------------------- The last functionality (for now) is the `ilo_license` type, which you can use to install licenses. .. code-block:: puppet ilo_license { "iLO 3 Advanced": key => "12345-67890-ABCDE-FGHIJ-KLMNO" } Note that the spelling of the license name is important. If it's not exactly the same as what `get_all_licenses` shows, puppet will try to activate the license again and again. Complete example ---------------- And here's a complete example to put all the above together. `/etc/puppet/device.conf`:: [server-001.ilo.kaarsemaker.net] type ilo url http://server-001.ilo.kaarsemaker.net `/etc/puppet/manifests/nodes.pp` .. code-block:: puppet node 'management-server.kaarsemaker.net' { include s_mgmt } node 'server-001.ilo.kaarsemaker.net' { include s_ilo } node 'server-002.ilo.kaarsemaker.net' { include s_ilo } node 'server-003.ilo.kaarsemaker.net' { include s_ilo } `/etc/puppet/modules/s_mgmt/manifests/init.pp` .. code-block:: puppet class s_mgmt { class{'ilo::proxy': devices => [ "http://server-001.ilo.kaarsemaker.net", "http://server-002.ilo.kaarsemaker.net", "http://server-003.ilo.kaarsemaker.net", ] } } `/etc/puppet/modules/s_ilo/manifests/init.pp` .. code-block:: puppet class s_ilo { # Always upgrade firmware ilo_firmware { $management_processor: ensure => "latest", http_proxy => "http://webproxy:3128" } # We only have iLO 3's in this setup, so one license will do ilo_license { "iLO 3 Advanced": key => "12345-67890-ABCDE-FGHIJ-KLMNO" } ilo_settings { "global": settings => { "remote_console_port" => 23, "enforce_aes" => true, "f8_login_required" => true, }; "network": settings => { "prim_dns_server" => "10.42.1.31", "sec_dns_server" => "10.42.1.32", }; } ilo_user { "Administrator": # Temporary until changed everywhere password => 'P4ssw0rd', "dennis": ensure => present, display_name => 'Dennis Kaarsemaker', password_atcreate => 'MyPass!', reset_server_priv => false; # Remove leavers ["jack", "bob"]: ensure => absent, } } python-hpilo-3.6/docs/input.rst0000644000175000017500000000057012652734620017430 0ustar dennisdennis00000000000000Keyboard and mouse settings =========================== .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_hotkey_config .. ilo_output:: get_hotkey_config .. automethod:: hotkey_config .. automethod:: get_pers_mouse_keyboard_enabled .. ilo_output:: get_pers_mouse_keyboard_enabled .. automethod:: set_pers_mouse_keyboard_enabled python-hpilo-3.6/docs/snmp.rst0000644000175000017500000000067612652734620017255 0ustar dennisdennis00000000000000SNMP settings ============= Besides looking at the :doc:`health data ` via this API, you can also monitor the iLO using the standard SNMP protocol. It can even forward SNMP requests to the host. With these functions you can tell the iLO what to do for SNMP. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_snmp_im_settings .. ilo_output:: get_snmp_im_settings .. automethod:: mod_snmp_im_settings python-hpilo-3.6/docs/license.rst0000644000175000017500000000056712652734620017721 0ustar dennisdennis00000000000000iLO licensing ============= Several iLO features are only available if you have an iLO advanced license. These functions can tell you whether such a license has been activated and allow you to activate one. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: get_all_licenses .. ilo_output:: get_all_licenses .. automethod:: activate_license python-hpilo-3.6/docs/boot.rst0000644000175000017500000000200112652734620017223 0ustar dennisdennis00000000000000Boot settings and rebooting =========================== HP servers can boot in various ways and from many devices. The functions in this section let you manipulate bootup settings and reboot the server and the iLO. If you need to power off the server hard, take a look at the :doc:`power documentation `. .. py:currentmodule:: hpilo .. class:: Ilo :noindex: .. automethod:: reset_rib .. automethod:: reset_server .. automethod:: cold_boot_server .. automethod:: warm_boot_server .. automethod:: get_one_time_boot .. ilo_output:: get_one_time_boot .. automethod:: set_one_time_boot .. automethod:: get_persistent_boot .. ilo_output:: get_persistent_boot .. automethod:: set_persistent_boot .. automethod:: get_supported_boot_mode .. ilo_output:: get_supported_boot_mode .. automethod:: get_current_boot_mode .. ilo_output:: get_current_boot_mode .. automethod:: get_pending_boot_mode .. ilo_output:: get_pending_boot_mode .. automethod:: set_pending_boot_mode python-hpilo-3.6/docs/elasticsearch.rst0000644000175000017500000000441012652734620021100 0ustar dennisdennis00000000000000iLO information search ====================== When managing large amounts of iLOs, it's often useful to be able to quickly search through iLO configuration data without having to query them all. The approach chosen in this example is to store all available information in elasticsearch. Storing information ------------------- While the application can query the iLO itself, it does need to be told the names (or IP addresses, but names are recommended) of your iLO interfaces. To do this, you will need to create a `servers.py` file that will tell the application what it wants. An example `servers.py` is shipped with the application that simply returns a static list of hostnames, but you could do anything here. The author uses a variant that queries an asset database to get the iLO names for example. Once you have created `servers.py` to match your environment, you can run :command:`hpilo_es_import`. It will connect to elasticsearch on localhost and create an index named `hpilo`. If elasticsearch does not live on localhost, you can tell the application this in :file:`~/.ilo.conf`:: [elasticsearch] host = elasticsearch.example.com The importer will then contact all your iLOs and call the `get_fw_version`, `get_host_data`, `get_global_settings`, `get_network_settings`, `get_all_user_info`, `get_oa_info` and `xmldata` methods to get a bunch of information from the iLO. All this is then stored in elasticsearch. Once you have this working, all that remains is to set up a cronjob to regularly run the importer to refresh the data. Retrieving information ---------------------- Of course data is useless if you cannot retrieve it. Since there is nothing special about the iLO data, you can fetch it from elasticsearch like you fetch any data from there. The example includes an application that dumps all data, but the most useful code here you will need to write yourself, or you can use a visualization tool like kibana to look at the data. Kibana dashboard ---------------- Kibana is a really powerful dashboard solution for elasticsearch. You can use it to get a quick overview of your iLO versions, settings and health data. You can find an example dashboard in the directory of this example application that you can import in your Kibana 4 instance. .. image:: _static/kibana.png python-hpilo-3.6/PKG-INFO0000644000175000017500000000142112652734620015700 0ustar dennisdennis00000000000000Metadata-Version: 1.1 Name: python-hpilo Version: 3.6 Summary: iLO automation from python or shell Home-page: http://github.com/seveas/python-hpilo Author: Dennis Kaarsemaker Author-email: dennis@kaarsemaker.net License: UNKNOWN Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: System :: Hardware Classifier: Topic :: System :: Systems Administration Classifier: Topic :: System :: Networking python-hpilo-3.6/setup.py0000755000175000017500000000162112652734620016322 0ustar dennisdennis00000000000000#!/usr/bin/python from distutils.core import setup setup(name = "python-hpilo", version = "3.6", author = "Dennis Kaarsemaker", author_email = "dennis@kaarsemaker.net", url = "http://github.com/seveas/python-hpilo", description = "iLO automation from python or shell", py_modules = ["hpilo", "hpilo_fw"], scripts = ["hpilo_cli"], classifiers = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Intended Audience :: System Administrators', 'License :: OSI Approved :: GNU General Public License (GPL)', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Topic :: System :: Hardware', 'Topic :: System :: Systems Administration', 'Topic :: System :: Networking', ] ) python-hpilo-3.6/ilo.conf.example0000644000175000017500000000067312652734620017677 0ustar dennisdennis00000000000000[ilo] login = Administrator password = AdminPassword hponcfg = /usr/local/bin/hponcfg [license] ilo2_advanced = FAKEILO2LICENSEXXXXXXXXXX ilo3_advanced = FAKEI-LO3LI-CENSE-XXXXX-XXXXX [firmware] # mirror = http://firmware-mirror.example.com [ca] path = ~/.hpilo_ca # country = NL # state = Flevoland # locality = Lelystad # organization = Kaarsemaker.net # organizational_unit = Sysadmin [elasticsearch] # host = elasticsearch.example.com python-hpilo-3.6/hpilo.py0000644000175000017500000025470512652734620016307 0ustar dennisdennis00000000000000# (c) 2011-2016 Dennis Kaarsemaker # see COPYING for license details __version__ = "3.6" import os import errno import platform import random import re import socket import subprocess import sys import types import warnings import hpilo_fw PY3 = sys.version_info[0] >= 3 if PY3: import urllib.request as urllib2 import io as StringIO b = lambda x: bytes(x, 'ascii') class Bogus(Exception): pass socket.sslerror = Bogus basestring = str else: import urllib2 import cStringIO as StringIO b = lambda x: x try: import ssl except ImportError: # Fallback for older python versions class ssl: PROTOCOL_SSLv3 = 1 PROTOCOL_TLSv23 = 2 PROTOCOL_TLSv1 = 3 @staticmethod def wrap_socket(sock, *args, **kwargs): return ssl(sock) def __init__(self, sock): self.sock = sock self.sslsock = socket.ssl(sock) def read(self, n=None): if not n: return self.sslsock.read() return self.sslsock.read(n) def write(self, data): return self.sslsock.write(data) def shutdown(self, what): return self.sock.shutdown(what) def close(self): return self.sock.close() try: import xml.etree.ElementTree as etree except ImportError: import elementtree.ElementTree as etree # Oh the joys of monkeypatching... # - We need a CDATA element in set_security_msg, but ElementTree doesn't support it # - We need to disable escaping of the PASSWORD attribute, because iLO doesn't # unescape it properly def CDATA(text=None): element = etree.Element('![CDATA[') element.text = text return element # Adding this tag to RIBCL scripts should make this hack unnecessary in newer # iLO firmware versions. TODO: Check compatibility. # class DoNotEscapeMe(str): pass etree._original_escape_attrib = etree._escape_attrib def _escape_attrib(text, *args, **kwargs): if isinstance(text, DoNotEscapeMe): return str(text) else: return etree._original_escape_attrib(text, *args, **kwargs) etree._escape_attrib = _escape_attrib # Python 2.7 and 3 if hasattr(etree, '_serialize_xml'): etree._original_serialize_xml = etree._serialize_xml def _serialize_xml(write, elem, *args, **kwargs): if elem.tag == '![CDATA[': write("\n<%s%s]]>\n" % (elem.tag, elem.text)) return return etree._original_serialize_xml(write, elem, *args, **kwargs) etree._serialize_xml = etree._serialize['xml'] = _serialize_xml # Python 2.5-2.6, and non-stdlib ElementTree elif hasattr(etree.ElementTree, '_write'): etree.ElementTree._orig_write = etree.ElementTree._write def _write(self, file, node, encoding, namespaces): if node.tag == '![CDATA[': file.write("\n\n" % node.text.encode(encoding)) else: self._orig_write(file, node, encoding, namespaces) etree.ElementTree._write = _write else: raise RuntimeError("Don't know how to monkeypatch XML serializer workarounds. Please report a bug at https://github.com/seveas/python-hpilo") # Which protocol to use ILO_RAW = 1 ILO_HTTP = 2 ILO_LOCAL = 3 class IloErrorMeta(type): def __new__(cls, name, parents, attrs): # Support old python versions where Exception is an old-style class if hasattr(types, 'ClassType') and type(Exception) == types.ClassType: parents = parents + (object,) if 'possible_messages' not in attrs: attrs['possible_messages'] = [] if 'possible_codes' not in attrs: attrs['possible_codes'] = [] klass = super(IloErrorMeta, cls).__new__(cls, name, parents, attrs) if name != 'IloError': IloError.known_subclasses.append(klass) return klass class IloError(Exception): __metaclass__ = IloErrorMeta def __init__(self, message, errorcode=None): if issubclass(IloError, object): super(IloError, self).__init__(message) else: Exception.__init__(self, message) self.errorcode = errorcode known_subclasses = [] class IloCommunicationError(IloError): pass class IloGeneratingCSR(IloError): possible_messages = ['The iLO subsystem is currently generating a Certificate Signing Request(CSR), run script after 10 minutes or more to receive the CSR.'] possible_codes = [0x0088] class IloLoginFailed(IloError): possible_messages = ['Login failed', 'Login credentials rejected'] possible_codes = [0x005f] class IloUserNotFound(IloError): possible_codes = [0x000a] class IloPermissionError(IloError): possible_codes = [0x0023] class IloNotARackServer(IloError): possible_codes = [0x002a] class IloLicenseKeyError(IloError): possible_codes = [0x002e] class IloFeatureNotSupported(IloError): possible_codes = [0x003c] class IloWarning(Warning): pass class IloTestWarning(Warning): pass class Ilo(object): """Represents an iLO/iLO2/iLO3/iLO4/RILOE II management interface on a specific host. A new connection using the specified login, password and timeout will be made for each API call. The library will detect which protocol to use, but you can override this by setting protocol to ILO_RAW or ILO_HTTP. Use ILO_LOCAL to avoid using a network connection and use hponcfg instead. Username and password are ignored for ILO_LOCAL connections. Set delayed to True to make python-hpilo not send requests immediately, but group them together. See :func:`call_delayed`""" XML_HEADER = b('\r\n') HTTP_HEADER = "POST /ribcl HTTP/1.1\r\nHost: localhost\r\nContent-Length: %d\r\nConnection: Close%s\r\n\r\n" HTTP_UPLOAD_HEADER = "POST /cgi-bin/uploadRibclFiles HTTP/1.1\r\nHost: localhost\r\nConnection: Close\r\nContent-Length: %d\r\nContent-Type: multipart/form-data; boundary=%s\r\n\r\n" BLOCK_SIZE = 64 * 1024 def __init__(self, hostname, login=None, password=None, timeout=60, port=443, protocol=None, delayed=False): self.hostname = hostname self.login = login or 'Administrator' self.password = password or 'Password' self.timeout = timeout self.debug = 0 self.port = port self.protocol = protocol self.cookie = None self.delayed = delayed self._elements = None self._processors = [] self.ssl_version = ssl.PROTOCOL_TLSv1 self.save_response = None self.read_response = None self.save_request = None self._protect_passwords = os.environ.get('HPILO_DONT_PROTECT_PASSWORDS', None) != 'YesPlease' self.firmware_mirror = None self.hponcfg = "/sbin/hponcfg" hponcfg = 'hponcfg' if platform.system() == 'Windows': self.hponcfg = 'C:\Program Files\HP Lights-Out Configuration Utility\cpqlocfg.exe' hponcfg = 'cpqlocfg.exe' for path in os.environ.get('PATH','').split(os.pathsep): maybe = os.path.join(path, hponcfg) if os.access(maybe, os.X_OK): self.hponcfg = maybe break def __str__(self): return "iLO interface of %s" % self.hostname def _debug(self, level, message): if message.__class__.__name__ == 'bytes': message = message.decode('latin-1') if self.debug >= level: if self._protect_passwords: message = re.sub(r'PASSWORD=".*?"', 'PASSWORD="********"', message) sys.stderr.write(message) if message.startswith('\r'): sys.stderr.flush() else: sys.stderr.write('\n') def _request(self, xml, progress=None): """Given an ElementTree.Element, serialize it and do the request. Returns an ElementTree.Element containing the response""" if not self.protocol and not self.read_response: self._detect_protocol() # Serialize the XML if hasattr(etree, 'tostringlist'): xml = b("\r\n").join(etree.tostringlist(xml)) + b('\r\n') else: xml = etree.tostring(xml) header, data = self._communicate(xml, self.protocol, progress=progress) # This thing usually contains multiple XML messages messages = [] while data: pos = data.find(''), ILO_HTTP, save=False) if header: self.protocol = ILO_HTTP else: self.protocol = ILO_RAW def _upload_file(self, filename, progress): firmware = open(filename, 'rb').read() boundary = b('------hpiLO3t' + str(random.randint(100000,1000000)) + 'z') while boundary in firmware: boundary = b('------hpiLO3t' + str(random.randint(100000,1000000)) + 'z') parts = [ b("--") + boundary + b("""\r\nContent-Disposition: form-data; name="fileType"\r\n\r\n"""), b("\r\n--") + boundary + b('''\r\nContent-Disposition: form-data; name="fwimgfile"; filename="''') + b(filename) + b('''"\r\nContent-Type: application/octet-stream\r\n\r\n'''), firmware, b("\r\n--") + boundary + b("--\r\n"), ] total_bytes = sum([len(x) for x in parts]) sock = self._get_socket() self._debug(2, self.HTTP_UPLOAD_HEADER % (total_bytes, boundary.decode('ascii'))) sock.write(b(self.HTTP_UPLOAD_HEADER % (total_bytes, boundary.decode('ascii')))) for part in parts: if len(part) < self.BLOCK_SIZE: self._debug(2, part) sock.write(part) else: sent = 0 fwlen = len(part) while sent < fwlen: written = sock.write(part[sent:sent+self.BLOCK_SIZE]) if written is None: plen = len(part[sent:sent+self.BLOCK_SIZE]) raise IloCommunicationError("Unexpected EOF while sending %d bytes (%d of %d sent before)" % (plen, sent, fwlen)) sent += written if callable(progress): progress("Sending request %d/%d bytes (%d%%)" % (sent, fwlen, 100.0*sent/fwlen)) data = '' try: while True: d = sock.read() data += d.decode('latin-1') if not d: break except socket.sslerror: # Connection closed e = sys.exc_info()[1] if not data: raise IloCommunicationError("Communication with %s:%d failed: %s" % (self.hostname, self.port, str(e))) self._debug(1, "Received %d bytes" % len(data)) self._debug(2, data) if 'Set-Cookie:' not in data: # Seen on ilo3 with corrupt filesystem body = re.search('(.*)', data, flags=re.DOTALL).group(1) body = re.sub('<[^>]*>', '', body).strip() body = re.sub('Return to last page', '', body).strip() body = re.sub('\s+', ' ', body).strip() raise IloError(body) self.cookie = re.search('Set-Cookie: *(.*)', data).group(1) self._debug(2, "Cookie: %s" % self.cookie) def _get_socket(self): """Set up a subprocess or an https connection and do an HTTP/raw socket request""" if self.read_response or self.save_request: class FakeSocket(object): def __init__(self, rfile=None, wfile=None): self.input = rfile and open(rfile) or StringIO.StringIO() self.output = wfile and open(wfile, 'a') or StringIO.StringIO() self.read = self.input.read self.write = self.output.write data = self.input.read(4) self.input.seek(0) self.protocol = data == 'HTTP' and ILO_HTTP or ILO_RAW def close(self): self.input.close() self.output.close() shutdown = lambda *args: None sock = FakeSocket(self.read_response, self.save_request) self.protocol = sock.protocol return sock if self.protocol == ILO_LOCAL: self._debug(1, "Launching hponcfg") try: sp = subprocess.Popen([self.hponcfg, '--input', '--xmlverbose'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: e = sys.exc_info()[1] raise IloCommunicationError("Cannot run %s: %s" % (self.hponcfg, str(e))) sp.write = sp.stdin.write sp.read = sp.stdout.read return sp self._debug(1, "Connecting to %s port %d" % (self.hostname, self.port)) err = None for res in socket.getaddrinfo(self.hostname, self.port, 0, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket.socket(af, socktype, proto) sock.settimeout(self.timeout) self._debug(2, "Connecting to %s port %d" % sa[:2]) sock.connect(sa) except socket.timeout: if sock is not None: sock.close() err = IloCommunicationError("Timeout connecting to %s port %d" % (self.hostname, self.port)) except socket.error: if sock is not None: sock.close() e = sys.exc_info()[1] err = IloCommunicationError("Error connecting to %s port %d: %s" % (self.hostname, self.port, str(e))) if err is not None: raise err if not sock: raise IloCommunicationError("Unable to resolve %s" % self.hostname) try: return ssl.wrap_socket(sock, ssl_version=self.ssl_version) except socket.sslerror: e = sys.exc_info()[1] msg = getattr(e, 'reason', None) or getattr(e, 'message', None) or str(e) # Some ancient iLO's don't support TLSv1, retry with SSLv3 if 'wrong version number' in msg and self.sslversion == ssl.PROTOCOL_TLSv1: self.ssl_version = ssl.PROTOCOL_SSLv3 return self._get_socket() raise IloCommunicationError("Cannot establish ssl session with %s:%d: %s" % (self.hostname, self.port, msg)) def _communicate(self, xml, protocol, progress=None, save=True): sock = self._get_socket() if self.read_response: protocol = sock.protocol msglen = msglen_ = len(self.XML_HEADER + xml) if protocol == ILO_HTTP: extra_header = '' if self.cookie: extra_header = "\r\nCookie: %s" % self.cookie http_header = self.HTTP_HEADER % (msglen, extra_header) msglen += len(http_header) self._debug(1, "Sending XML request, %d bytes" % msglen) if protocol == ILO_HTTP: self._debug(2, http_header) sock.write(b(http_header)) self._debug(2, self.XML_HEADER + xml) # XML header and data need to arrive in 2 distinct packets if self.protocol != ILO_LOCAL: sock.write(self.XML_HEADER) if b('$EMBED') in xml: pre, name, post = re.compile(b(r'(.*)\$EMBED:(.*)\$(.*)'), re.DOTALL).match(xml).groups() sock.write(pre) sent = 0 fwlen = os.path.getsize(name) fw = open(name, 'rb').read() while sent < fwlen: written = sock.write(fw[sent:sent+self.BLOCK_SIZE]) sent += written if callable(progress): progress("Sending request %d/%d bytes (%d%%)" % (sent, fwlen, 100.0*sent/fwlen)) sock.write(post.strip()) else: sock.write(xml) # And grab the data if self.save_request and save: sock.close() return None, None if self.protocol == ILO_LOCAL: # hponcfg doesn't return data until stdin is closed sock.stdin.close() data = '' try: while True: d = sock.read().decode('latin-1') data += d if not d: break if callable(progress) and d.strip().endswith(''): d = d[d.find('')+1] if self.save_response and save: fd = open(self.save_response, 'a') fd.write(data) fd.close() # Do we have HTTP? header_ = '' if protocol == ILO_HTTP and data.startswith('HTTP/1.1 200'): header, data = data.split('\r\n\r\n', 1) header_ = header header = [x.split(':', 1) for x in header.split('\r\n')[1:]] header = dict([(x[0].lower(), x[1].strip()) for x in header]) if header['transfer-encoding'] == 'chunked': _data, data = data, '' while _data: clen, _data = _data.split('\r\n', 1) clen = int(clen, 16) if clen == 0: break data += _data[:clen] _data = _data[clen+2:] elif data.startswith('HTTP/1.1 404'): # We must be using iLO2 or older, they don't do HTTP for XML requests # This case is only triggered by the protocol detection header = None elif not data.startswith('' in data: data = data.replace('', '') if re.search(r'''=+ *[^"'\n=]''', data): data = re.sub(r'''= *([^"'\n]+?) *\n''', r'="\1"', data) data = data.strip() if not data: return None message = etree.fromstring(data) if message.tag == 'RIBCL': for child in message: if child.tag == 'INFORM': if include_inform: # Filter useless message: if 'should be updated' in child.text: return None return child.text # RESPONE with status 0 also adds no value # Maybe start adding to requests. TODO: check compatibility elif child.tag == 'RESPONSE' and int(child.get('STATUS'), 16) == 0: if child.get('MESSAGE') != 'No error': warnings.warn(child.get('MESSAGE'), IloWarning) # These are interesting, something went wrong elif child.tag == 'RESPONSE': if 'syntax error' in child.get('MESSAGE') and not self.protocol: # This is triggered when doing protocol detection, ignore pass else: status = int(child.get('STATUS'), 16) message = child.get('MESSAGE') if 'syntax error' in message: message += '. You may have tried to use a feature this iLO version or firmware version does not support.' for subclass in IloError.known_subclasses: if status in subclass.possible_codes or message in subclass.possible_messages: raise subclass(message, status) raise IloError(message, status) # And this type of message is the actual payload. else: return message return None # This shouldn't be reached as all messages are RIBCL messages. But who knows! return message def _element_children_to_dict(self, element): """Returns a dict with tag names of all child elements as keys and the VALUE attributes as values""" retval = {} keys = [elt.tag.lower() for elt in element] if len(keys) != 1 and len(set(keys)) == 1: # Can't return a dict retval = [] for elt in element: # There are some special tags fname = '_parse_%s_%s' % (element.tag.lower(), elt.tag.lower()) if hasattr(self, fname): retval.update(getattr(self, fname)(elt)) continue key, val, unit, description = elt.tag.lower(), elt.get('VALUE', elt.get('value', None)), elt.get('UNIT', None), elt.get('DESCRIPTION', None) if val is None: # HP is not best friends with consistency. Sometimes there are # attributes, sometimes child tags and sometimes text nodes. Oh # well, deal with it :) if element.tag.lower() == 'rimp' or elt.tag.lower() in self.xmldata_ectd.get(element.tag.lower(), []) or elt.tag.lower() == 'temps': val = self._element_children_to_dict(elt) elif elt.attrib and list(elt): val = self._element_to_dict(elt) elif list(elt): val = self._element_to_list(elt) elif elt.text: val = elt.text.strip() elif elt.attrib: val = self._element_to_dict(elt) val = self._coerce(val) if unit: val = (val, unit) if description and isinstance(val, str): val = (val, description) if isinstance(retval, list): retval.append(val) elif key in retval: if isinstance(retval[key], dict): retval[key].update(val) elif not isinstance(retval[key], list): retval[key] = [retval[key], val] else: retval[key].append(val) else: retval[key] = val return retval def _element_to_dict(self, element): """Returns a dict with tag attributes as items""" retval = {} for key, val in element.attrib.items(): retval[key.lower()] = self._coerce(val) if list(element): fields = [] for child in element.getchildren(): if child.tag == 'FIELD': fields.append(self._element_to_dict(child)) if fields: names = [x['name'] for x in fields] if len(names) == len(set(names)): # Field names are unique, treat them like attributes for field in fields: retval[field['name']] = field['value'] else: # Field names are not unique, such as the name "MAC" retval['fields'] = fields return retval def _element_to_list(self, element): tagnames = [x.tag for x in element] if len(set(tagnames)) == 1: return [self._element_children_to_dict(x) for x in element] else: return [(child.tag.lower(), self._element_to_dict(child)) for child in element] def _coerce(self, val): """Do some data type coercion: unquote, turn integers into integers and Y/N into booleans""" if isinstance(val, basestring): if val.startswith('"') and val.endswith('"'): val = val[1:-1] if val.isdigit(): val = int(val) else: val = {'Y': True, 'N': False, 'true': True, 'false': False}.get(val, val) return val def _raw(self, *tags): if self.delayed: raise IloError("Cannot use raw tags in delayed mode") root, inner = self._root_element(tags[0][0], **(tags[0][1])) for t in tags[1:]: inner = etree.SubElement(inner, t[0], **t[1]) header, message = self._request(root) fd = StringIO.StringIO() etree.ElementTree(message).write(fd) ret = fd.getvalue() fd.close() return ret def _info_tag(self, infotype, tagname, returntags=None, attrib={}, process=lambda x: x): root, inner = self._root_element(infotype, MODE='read') etree.SubElement(inner, tagname, **attrib) if self.delayed: self._processors.append([self._process_info_tag, returntags or [tagname], process]) return header, message = self._request(root) if self.save_request: return return self._process_info_tag(message, returntags or [tagname], process) def _process_info_tag(self, message, returntags, process): if isinstance(returntags, basestring): returntags = [returntags] for tag in returntags: if message.find(tag) is None: continue message = message.find(tag) if list(message): return process(self._element_children_to_dict(message)) else: return process(self._element_to_dict(message)) raise IloError("Expected tag '%s' not found" % "' or '".join(returntags)) def _control_tag(self, controltype, tagname, returntag=None, attrib={}, elements=[], text=None): root, inner = self._root_element(controltype, MODE='write') inner = etree.SubElement(inner, tagname, **attrib) if text: inner.text = text for element in elements: inner.append(element) if self.delayed: if tagname == 'CERTIFICATE_SIGNING_REQUEST': self._processors.append([self._process_control_tag, returntag or tagname]) return header, message = self._request(root) return self._process_control_tag(message, returntag or tagname) def _process_control_tag(self, message, returntag): if message is None: return None message = message.find(returntag) if message.text.strip(): return message.text.strip() if not message.attrib and not list(message): return None raise IloError("You've reached unknown territories, please report a bug") if list(message): return self._element_children_to_dict(message) else: return self._element_to_dict(message) def call_delayed(self): """In delayed mode, calling a method on an iLO object will not cause an immediate callout to the iLO. Instead, the method and parameters are stored for future calls of this method. This method makes one connection to the iLO and sends all commands as one XML document. This speeds up applications that make many calls to the iLO by removing seconds of overhead per call. The return value of call_delayed is a list of return values for individual methods that don't return None. This means that there may be fewer items returned than methods called as only `get_*` methods return data Delayed calls only work on iLO 2 or newer""" if not self._elements: raise ValueError("No commands scheduled") root, inner = self._elements header, message = self._request(root) ret = [] if message is not None: if not isinstance(message, list): message = [message] for message, processor in zip(message, self._processors): ret.append(processor.pop(0)(message, *processor)) self._processors = [] self._elements = None return ret def activate_license(self, key): """Activate an iLO advanced license""" license = etree.Element('ACTIVATE', KEY=key) return self._control_tag('RIB_INFO', 'LICENSE', elements=[license]) def add_federation_group(self, group_name, group_key, admin_priv=False, remote_cons_priv=True, reset_server_priv=False, virtual_media_priv=False, config_ilo_priv=True, login_priv=False): """Add a new federation group""" attrs = locals() elements = [] for attribute in [x for x in attrs.keys() if x.endswith('_priv')]: val = ['No', 'Yes'][bool(attrs[attribute])] elements.append(etree.Element(attribute.upper(), VALUE=val)) return self._control_tag('RIB_INFO', 'ADD_FEDERATION_GROUP', elements=elements, attrib={'GROUP_NAME': group_name, 'GROUP_KEY': group_key}) def add_user(self, user_login, user_name, password, admin_priv=False, remote_cons_priv=True, reset_server_priv=False, virtual_media_priv=False, config_ilo_priv=True): """Add a new user to the iLO interface with the specified name, password and permissions. Permission attributes should be boolean values.""" attrs = locals() elements = [] for attribute in [x for x in attrs.keys() if x.endswith('_priv')]: val = ['No', 'Yes'][bool(attrs[attribute])] elements.append(etree.Element(attribute.upper(), VALUE=val)) return self._control_tag('USER_INFO', 'ADD_USER', elements=elements, attrib={'USER_LOGIN': user_login, 'USER_NAME': user_name, 'PASSWORD': DoNotEscapeMe(password)}) def ahs_clear_data(self): """Clears Active Health System information log""" return self._control_tag('RIB_INFO', 'AHS_CLEAR_DATA') def cert_fqdn(self, use_fqdn): """Configure whether to use the fqdn or the short hostname for certificate requests""" use_fqdn = str({True: 'Yes', False: 'No'}.get(use_fqdn, use_fqdn)) return self._control_tag('RIB_INFO', 'CERT_FQDN', attrib={'VALUE': use_fqdn}) def certificate_signing_request(self, country=None, state=None, locality=None, organization=None, organizational_unit=None, common_name=None): """Get a certificate signing request from the iLO""" vars = locals() del vars['self'] vars = [('CSR_' + x.upper(), vars[x]) for x in vars if vars[x]] elements = map(lambda x: etree.Element(x[0], attrib={'VALUE': str(x[1])}), vars) return self._control_tag('RIB_INFO', 'CERTIFICATE_SIGNING_REQUEST', elements=elements) def clear_ilo_event_log(self): """Clears the iLO event log""" return self._control_tag('RIB_INFO', 'CLEAR_EVENTLOG') def clear_server_event_log(self): """Clears the server event log""" return self._control_tag('SERVER_INFO', 'CLEAR_IML') def clear_server_power_on_time(self): """Clears the server power on time""" return self._control_tag('SERVER_INFO', 'CLEAR_SERVER_POWER_ON_TIME') def computer_lock_config(self, computer_lock=None, computer_lock_key=None): """Configure the computer lock settings""" if computer_lock_key: computer_lock = "custom" if not computer_lock: raise ValueError("A value must be specified for computer_lock") elements = [etree.Element('COMPUTER_LOCK', VALUE=computer_lock)] if computer_lock_key: elements.append(etree.Element('COMPUTER_LOCK_KEY', VALUE=computer_lock_key)) return self._control_tag('RIB_INFO', 'COMPUTER_LOCK_CONFIG', elements=elements) def dc_registration_complete(self): """Complete the ERS registration of your device after calling set_ers_direct_connect""" return self._control_tag('RIB_INFO', 'DC_REGISTRATION_COMPLETE') def delete_federation_group(self, group_name): """Delete the specified federation group membership""" return self._control_tag('RIB_INFO', 'DELETE_FEDERATION_GROUP', attrib={'GROUP_NAME': group_name}) def delete_user(self, user_login): """Delete the specified user from the ilo""" return self._control_tag('USER_INFO', 'DELETE_USER', attrib={'USER_LOGIN': user_login}) def disable_ers(self): """Disable Insight Remote Support functionality and unregister the server""" return self._control_tag('RIB_INFO', 'DISABLE_ERS') def eject_virtual_floppy(self): """Eject the virtual floppy""" return self._control_tag('RIB_INFO', 'EJECT_VIRTUAL_FLOPPY') def eject_virtual_media(self, device="cdrom"): """Eject the virtual media attached to the specified device""" return self._control_tag('RIB_INFO', 'EJECT_VIRTUAL_MEDIA', attrib={"DEVICE": device.upper()}) def ers_ahs_submit(self, message_id, bb_days): """Submity AHS data to the insight remote support server""" elements = [ etree.Element('MESSAGE_ID', attrib={'VALUE': str(message_id)}), etree.Element('BB_DAYS', attrib={'VALUE': str(bb_days)}), ] return self._control_tag('RIB_INFO', 'TRIGGER_BB_DATA', elements=elements) def fips_enable(self): """Enable FIPS standard to enforce AES/3DES encryption, can only be reset with a call to factory_defaults. Resets Administrator password and license key""" return self._control_tag('RIB_INFO', 'FIPS_ENABLE') def factory_defaults(self): """Reset the iLO to factory default settings""" return self._control_tag('RIB_INFO', 'FACTORY_DEFAULTS') def get_ahs_status(self): """Get active health system logging status""" return self._info_tag('RIB_INFO', 'GET_AHS_STATUS') def get_all_users(self): """Get a list of all loginnames""" def process(data): if isinstance(data, dict): data = data.values() return [x for x in data if x] return self._info_tag('USER_INFO', 'GET_ALL_USERS', process=process) def get_all_user_info(self): """Get basic and authorization info of all users""" def process(data): if isinstance(data, dict): data = data.values() return dict([(x['user_login'], x) for x in data]) return self._info_tag('USER_INFO', 'GET_ALL_USER_INFO', process=process) def get_asset_tag(self): """Gets the server asset tag""" # The absence of an asset tag is communicated in a warning and there # will be *NO* returntag, hence the AttributeError. try: return self._info_tag('SERVER_INFO', 'GET_ASSET_TAG') except AttributeError: return {'asset_tag': None} def get_cert_subject_info(self): """Get ssl certificate subject information""" return self._info_tag('RIB_INFO', 'GET_CERT_SUBJECT_INFO', 'CSR_CERT_SETTINGS') def get_current_boot_mode(self): """Get the current boot mode (legaci or uefi)""" return self._info_tag('SERVER_INFO', 'GET_CURRENT_BOOT_MODE', process=lambda data: data['boot_mode']) def get_dir_config(self): """Get directory authentication configuration""" return self._info_tag('DIR_INFO', 'GET_DIR_CONFIG') def get_embedded_health(self): """Get server health information""" def process(data): for category in data: if category == 'health_at_a_glance': health = {} for key, val in data[category]: if key not in health: health[key] = val else: health[key].update(val) data[category] = health continue elif isinstance(data[category], list) and data[category]: for tag in ('label', 'location'): if tag in data[category][0]: data[category] = dict([(x[tag], x) for x in data[category]]) break elif data[category] in ['', []]: data[category] = None return data return self._info_tag('SERVER_INFO', 'GET_EMBEDDED_HEALTH', 'GET_EMBEDDED_HEALTH_DATA', process=process) # Ok, special XML structures. Yay. def _parse_get_embedded_health_data_drives(self, element): ret = [] for bp in element: if bp.tag != 'BACKPLANE': raise IloError("Unexpected data returned: %s" % bp.tag) backplane = obj = {'drive_bays': {}} ret.append(backplane) for elt in bp: if elt.tag == 'DRIVE_BAY': obj = {} backplane['drive_bays'][int(elt.get('VALUE'))] = obj else: obj[elt.tag.lower()] = elt.get('VALUE') return {'drives_backplanes': ret} def _parse_get_embedded_health_data_memory(self, element): ret = {} for elt in element: fname = '_parse_%s_%s' % (element.tag.lower(), elt.tag.lower()) if hasattr(self, fname): ret.update(getattr(self, fname)(elt)) continue ret[elt.tag.lower()] = self._element_children_to_dict(elt) return {element.tag.lower(): ret} _parse_memory_memory_details_summary = _parse_get_embedded_health_data_memory def _parse_memory_memory_details(self, element): ret = {} for elt in element: if elt.tag not in ret: ret[elt.tag] = {} data = self._element_children_to_dict(elt) ret[elt.tag]["socket %d" % data["socket"]] = data return {element.tag.lower(): ret} def _parse_get_embedded_health_data_nic_information(self, element): ret = {} for elt in element: data = self._element_children_to_dict(elt) ret['%s %s' % (elt.tag, data['network_port'])] = data return {'nic_information': ret} # Can you notice the misspelling?Yes, this is an actual bug in the HP firmware, seen in at least ilo3 1.70 _parse_get_embedded_health_data_nic_infomation = _parse_get_embedded_health_data_nic_information def _parse_get_embedded_health_data_firmware_information(self, element): ret = {} for elt in element: data = self._element_children_to_dict(elt) ret[data['firmware_name']] = data['firmware_version'] return {element.tag.lower(): ret} def _parse_get_embedded_health_data_storage(self, element): key = element.tag.lower() ret = {key: []} for ctrl in element: if ctrl.tag == 'DISCOVERY_STATUS': ret['%s_%s' % (key, ctrl.tag.lower())] = self._element_children_to_dict(ctrl)['status'] continue data = {} for elt in ctrl: tag = elt.tag.lower() if tag in ('drive_enclosure', 'logical_drive'): tag += 's' if tag not in data: data[tag] = [] if tag == 'drive_enclosures': data[tag].append(self._element_children_to_dict(elt)) else: data[tag].append(self._parse_logical_drive(elt)) else: data[tag] = elt.get('VALUE') ret[key].append(data) return ret def _parse_logical_drive(self, element): data = {} for elt in element: tag = elt.tag.lower() if tag == 'physical_drive': tag += 's' if tag not in data: data[tag] = [] data[tag].append(self._element_children_to_dict(elt)) else: data[tag] = elt.get('VALUE') return data def _parse_get_embedded_health_data_power_supplies(self, element): key = element.tag.lower() ret = {key: {}} for elt in element: data = self._element_children_to_dict(elt) if 'label' in data: ret[key][data['label']] = data else: ret[elt.tag.lower()] = data return ret def get_encrypt_settings(self): """Get the iLO encryption settings""" return self._info_tag('RIB_INFO', 'GET_ENCRYPT_SETTINGS') def get_ers_settings(self): """Get the ERS Insight Remote Support settings""" return self._info_tag('RIB_INFO', 'GET_ERS_SETTINGS') def get_federation_all_groups(self): """Get all federation group names""" def process(data): if isinstance(data, dict): data = data.values() return data return self._info_tag('RIB_INFO', 'GET_FEDERATION_ALL_GROUPS', process=process) def get_federation_all_groups_info(self): """Get all federation group names and associated privileges""" def process(data): if isinstance(data, dict): data = data.values() data = [dict([(key, {'yes': True, 'no': False}.get(val['value'].lower(), val['value'])) for (key, val) in group]) for group in data] return dict([(x['group_name'], x) for x in data]) return self._info_tag('RIB_INFO', 'GET_FEDERATION_ALL_GROUPS_INFO', process=process) def get_federation_group(self, group_name): """Get privileges for a specific federation group""" def process(data): return dict([(key, {'yes': True, 'no': False}.get(val['value'].lower(), val['value'])) for (key, val) in data.values()[0]]) return self._info_tag('RIB_INFO', 'GET_FEDERATION_GROUP', attrib={'GROUP_NAME': group_name}, process=process) def get_federation_multicast(self): """Get the iLO federation mulicast settings""" return self._info_tag('RIB_INFO', 'GET_FEDERATION_MULTICAST') def get_fips_status(self): """Is the FIPS-mandated AES/3DESencryption enforcement in place""" return self._info_tag('RIB_INFO', 'GET_FIPS_STATUS') def get_fw_version(self): """Get the iLO type and firmware version, use get_product_name to get the server model""" return self._info_tag('RIB_INFO', 'GET_FW_VERSION') def get_global_settings(self): """Get global iLO settings""" return self._info_tag('RIB_INFO', 'GET_GLOBAL_SETTINGS') def get_host_data(self, decoded_only=True): """Get SMBIOS records that describe the host. By default only the ones where human readable information is available are returned. To get all records pass :attr:`decoded_only=False` """ def process(data): if decoded_only: data = [x for x in data if len(x) > 2] return data return self._info_tag('SERVER_INFO', 'GET_HOST_DATA', process=process) def get_host_power_saver_status(self): """Get the configuration of the ProLiant power regulator""" return self._info_tag('SERVER_INFO', 'GET_HOST_POWER_SAVER_STATUS', 'GET_HOST_POWER_SAVER') def get_host_power_status(self): """Whether the server is powered on or not""" return self._info_tag('SERVER_INFO', 'GET_HOST_POWER_STATUS', 'GET_HOST_POWER', process=lambda data: data['host_power']) def get_host_pwr_micro_ver(self): """Get the version of the power micro firmware""" return self._info_tag('SERVER_INFO', 'GET_HOST_PWR_MICRO_VER', process=lambda data: data['pwr_micro']['version']) def get_ilo_event_log(self): """Get the full iLO event log""" def process(data): if isinstance(data, dict) and 'event' in data: return [data['event']] return data return self._info_tag('RIB_INFO', 'GET_EVENT_LOG', 'EVENT_LOG', process=process) def get_language(self): """Get the default language set""" return self._info_tag('RIB_INFO', 'GET_LANGUAGE') def get_all_languages(self): """Get the list of installed languages - broken because iLO returns invalid XML""" return self._info_tag('RIB_INFO', 'GET_ALL_LANGUAGES') def get_all_licenses(self): """Get a list of all license types and licenses""" def process(data): if not isinstance(data, list): data = data.values() return [dict([(x[0], x[1]['value']) for x in row]) for row in data] return self._info_tag('RIB_INFO', 'GET_ALL_LICENSES', process=process) def get_hotkey_config(self): """Retrieve hotkeys available for use in remote console sessions""" return self._info_tag('RIB_INFO', 'GET_HOTKEY_CONFIG') def get_network_settings(self): """Get the iLO network settings""" return self._info_tag('RIB_INFO', 'GET_NETWORK_SETTINGS') def get_oa_info(self): """Get information about the Onboard Administrator of the enclosing chassis""" return self._info_tag('BLADESYSTEM_INFO', 'GET_OA_INFO') def get_one_time_boot(self): """Get the one time boot state of the host""" # Inconsistency between iLO 2 and 3, let's fix that def process(data): if 'device' in data['boot_type']: data['boot_type'] = data['boot_type']['device'] return data['boot_type'].lower() return self._info_tag('SERVER_INFO', 'GET_ONE_TIME_BOOT', ('ONE_TIME_BOOT', 'GET_ONE_TIME_BOOT'), process=process) def get_pending_boot_mode(self): """Get the pending boot mode (legaci or uefi)""" return self._info_tag('SERVER_INFO', 'GET_PENDING_BOOT_MODE', process=lambda data: data['boot_mode']) def get_persistent_boot(self): """Get the boot order of the host. For uEFI hosts (gen9+), this returns a list of tuples (name, description. For older host it returns a list of names""" def process(data): if isinstance(data, dict): data = list(data.items()) data.sort(key=lambda x: x[1]) return [x[0].lower() for x in data] elif isinstance(data[0], tuple): return data return [x.lower() for x in data] return self._info_tag('SERVER_INFO', 'GET_PERSISTENT_BOOT', ('PERSISTENT_BOOT', 'GET_PERSISTENT_BOOT'), process=process) def get_pers_mouse_keyboard_enabled(self): """Returns whether persistent mouse and keyboard are enabled""" return self._info_tag('SERVER_INFO', 'GET_PERS_MOUSE_KEYBOARD_ENABLED', process=lambda data: data['persmouse_enabled']) def get_power_cap(self): """Get the power cap setting""" return self._info_tag('SERVER_INFO', 'GET_POWER_CAP', process=lambda data: data['power_cap']) def get_power_readings(self): """Get current, min, max and average power readings""" return self._info_tag('SERVER_INFO', 'GET_POWER_READINGS') def get_product_name(self): """Get the model name of the server, use get_fw_version to get the iLO model""" return self._info_tag('SERVER_INFO', 'GET_PRODUCT_NAME', process=lambda data: data['product_name']) def get_pwreg(self): """Get the power and power alert threshold settings""" return self._info_tag('SERVER_INFO', 'GET_PWREG') def get_rack_settings(self): """Get the rack settings for an iLO""" return self._info_tag('RACK_INFO', 'GET_RACK_SETTINGS') def get_security_msg(self): """Retrieve the security message that is displayed on the login screen""" return self._info_tag('RIB_INFO', 'GET_SECURITY_MSG') def get_server_auto_pwr(self): """Get the automatic power on delay setting""" return self._info_tag('SERVER_INFO', 'GET_SERVER_AUTO_PWR', process=lambda data: data['server_auto_pwr']) def get_server_event_log(self): """Get the IML log of the server""" def process(data): if isinstance(data, dict) and 'event' in data: return [data['event']] return data return self._info_tag('SERVER_INFO', 'GET_EVENT_LOG', 'EVENT_LOG', process=process) def get_server_fqdn(self): """Get the fqdn of the server this iLO is managing""" return self._info_tag('SERVER_INFO', 'GET_SERVER_FQDN', 'SERVER_FQDN', process=lambda fqdn: fqdn['value']) def get_server_name(self): """Get the name of the server this iLO is managing""" return self._info_tag('SERVER_INFO', 'GET_SERVER_NAME', 'SERVER_NAME', process=lambda name: name['value']) def get_server_power_on_time(self): """How many minutes ago has the server been powered on""" return self._info_tag('SERVER_INFO', 'GET_SERVER_POWER_ON_TIME', 'SERVER_POWER_ON_MINUTES', process=lambda data: int(data['value'])) def get_smh_fqdn(self): """Get the fqdn of the HP System Management Homepage""" return self._info_tag('SERVER_INFO', 'GET_SMH_FQDN', 'SMH_FQDN', process=lambda fqdn: fqdn['value']) def get_snmp_im_settings(self): """Where does the iLO send SNMP traps to and which traps does it send""" return self._info_tag('RIB_INFO', 'GET_SNMP_IM_SETTINGS') def get_spatial(self): """Get location information""" return self._info_tag('SERVER_INFO', 'GET_SPATIAL', 'SPATIAL') def get_sso_settings(self): """Get the HP SIM Single Sign-On settings""" return self._info_tag('SSO_INFO', 'GET_SSO_SETTINGS') def get_supported_boot_mode(self): return self._info_tag('SERVER_INFO', 'GET_SUPPORTED_BOOT_MODE', process=lambda data: data['supported_boot_mode']) def get_tpm_status(self): """Get the status of the Trusted Platform Module""" return self._info_tag('SERVER_INFO', 'GET_TPM_STATUS') def get_twofactor_settings(self): """Get two-factor authentication settings""" return self._info_tag('RIB_INFO', 'GET_TWOFACTOR_SETTINGS') def get_uid_status(self): """Get the status of the UID light""" return self._info_tag('SERVER_INFO', 'GET_UID_STATUS', process=lambda data: data['uid']) def get_user(self, user_login): """Get user info about a specific user""" return self._info_tag('USER_INFO', 'GET_USER', attrib={'USER_LOGIN': user_login}) def get_vm_status(self, device="CDROM"): """Get the status of virtual media devices. Valid devices are FLOPPY and CDROM""" return self._info_tag('RIB_INFO', 'GET_VM_STATUS', attrib={'DEVICE': device}) def hotkey_config(self, ctrl_t=None, ctrl_u=None, ctrl_v=None, ctrl_w=None, ctrl_x=None, ctrl_y=None): """Change remote console hotkeys""" vars = locals() del vars['self'] elements = [etree.Element(x.upper(), VALUE=vars[x]) for x in vars if vars[x] is not None] return self._control_tag('RIB_INFO', 'HOTKEY_CONFIG', elements=elements) def import_certificate(self, certificate): """Import a signed SSL certificate""" return self._control_tag('RIB_INFO', 'IMPORT_CERTIFICATE', text=certificate) # Broken in iLO3 < 1.55 for Administrator def import_ssh_key(self, user_login, ssh_key): """Imports an SSH key for the specified user. The value of ssh_key should be the content of an id_dsa.pub file""" # Basic sanity checking if ' ' not in ssh_key: raise ValueError("Invalid SSH key") algo, key = ssh_key.split(' ',2)[:2] if algo != 'ssh-dss': raise ValueError("Invalid SSH key, only DSA keys are supported") try: key.decode('base64') except Exception: raise ValueError("Invalid SSH key") key_ = "-----BEGIN SSH KEY-----\r\n%s\r\n%s %s\r\n-----END SSH KEY-----\r\n" % (algo, key, user_login) return self._control_tag('RIB_INFO', 'IMPORT_SSH_KEY', text=key_) def delete_ssh_key(self, user_login): """Delete a users SSH key""" return self._control_tag('USER_INFO', 'MOD_USER', attrib={'USER_LOGIN': user_login}, elements=[etree.Element('DEL_USERS_SSH_KEY')]) def insert_virtual_media(self, device, image_url): """Insert a virtual floppy or CDROM. Note that you will also need to use :func:`set_vm_status` to connect the media""" return self._control_tag('RIB_INFO', 'INSERT_VIRTUAL_MEDIA', attrib={'DEVICE': device.upper(), 'IMAGE_URL': image_url}) def mod_federation_group(self, group_name, new_group_name=None, group_key=None, admin_priv=None, remote_cons_priv=None, reset_server_priv=None, virtual_media_priv=None, config_ilo_priv=None, login_priv=None): """Set attributes for a federation group, only specified arguments will be changed. All arguments except group_name, new_group_name and group_key should be boolean""" attrs = locals() elements = [] if attrs['new_group_name'] is not None: elements.append(etree.Element('GROUP_NAME', VALUE=attrs['new_group_name'])) if attrs['group_key'] is not None: elements.append(etree.Element('PASSWORD', VALUE=attrs['group_key'])) for attribute in [x for x in attrs.keys() if x.endswith('_priv')]: if attrs[attribute] is not None: val = ['No', 'Yes'][bool(attrs[attribute])] elements.append(etree.Element(attribute.upper(), VALUE=val)) return self._control_tag('RIB_INFO', 'MOD_FEDERATION_GROUP', attrib={'GROUP_NAME': group_name}, elements=elements) def mod_global_settings(self, session_timeout=None, f8_prompt_enabled=None, f8_login_required=None, lock_configuration=None, ilo_funct_enabled=None, serial_cli_status=None, serial_cli_speed=None, http_port=None, https_port=None, ssh_port=None, ssh_status=None, vmedia_disable=None, virtual_media_port=None, remote_console_port=None, snmp_access_enabled=None, snmp_port=None, snmp_trap_port=None, remote_syslog_enable=None, remote_syslog_server_address=None, remote_syslog_port=None, alertmail_enable=None, alertmail_email_address=None, alertmail_sender_domain=None, alertmail_smtp_server=None, alertmail_smtp_port=None, min_password=None, enforce_aes=None, authentication_failure_logging=None, rbsu_post_ip=None, remote_console_encryption=None, remote_keyboard_model=None, terminal_services_port=None, high_performance_mouse=None, shared_console_enable=None, shared_console_port=None, remote_console_acquire=None, brownout_recovery=None, ipmi_dcmi_over_lan_enabled=None, vsp_log_enable=None, vsp_software_flow_control=None, propagate_time_to_host=None): """Modify iLO global settings, only values that are specified will be changed.""" vars = dict(locals()) del vars['self'] elements = [etree.Element(x.upper(), VALUE=str({True: 'Yes', False: 'No'}.get(vars[x], vars[x]))) for x in vars if vars[x] is not None] return self._control_tag('RIB_INFO', 'MOD_GLOBAL_SETTINGS', elements=elements) def mod_network_settings(self, enable_nic=None, reg_ddns_server=None, ping_gateway=None, dhcp_domain_name=None, speed_autoselect=None, nic_speed=None, full_duplex=None, dhcp_enable=None, ip_address=None, subnet_mask=None, gateway_ip_address=None, dns_name=None, domain_name=None, dhcp_gateway=None, dhcp_dns_server=None, dhcp_wins_server=None, dhcp_static_route=None, reg_wins_server=None, prim_dns_server=None, sec_dns_server=None, ter_dns_server=None, prim_wins_server=None, sec_wins_server=None, static_route_1=None, static_route_2=None, static_route_3=None, dhcp_sntp_settings=None, sntp_server1=None, sntp_server2=None, timezone=None, enclosure_ip_enable=None, web_agent_ip_address=None, shared_network_port=None, vlan_enabled=None, vlan_id=None, shared_network_port_vlan=None, shared_network_port_vlan_id=None, ipv6_address=None, ipv6_static_route_1=None, ipv6_static_route2=None, ipv6_static_route_3=None, ipv6_prim_dns_server=None, ipv6_sec_dns_server=None, ipv6_ter_dns_server=None, ipv6_default_gateway=None, ipv6_preferred_protocol=None, ipv6_addr_autocfg=None, ipv6_reg_ddns_server=None, dhcpv6_dns_server=None, dhcpv6_rapid_commit=None, dhcpv6_stateful_enable=None, dhcpv6_stateless_enable=None, dhcpv6_sntp_settings=None): """Configure the network settings for the iLO card. The static route arguments require dicts as arguments. The necessary keys in these dicts are dest, gateway and mask all in dotted-quad form""" vars = dict(locals()) del vars['self'] # For the ipv4 route elements, {'dest': XXX, 'gateway': XXX} # ipv6 routes are ipv6_dest, prefixlen, ipv6_gateway # IPv6 addresses may specify prefixlength as /64 (default 64) elements = [etree.Element(x.upper(), VALUE=str({True: 'Yes', False: 'No'}.get(vars[x], vars[x]))) for x in vars if vars[x] is not None and 'static_route_' not in x] for key in vars: if 'static_route_' not in key or not vars[key]: continue val = vars[key] # Uppercase all keys for key_ in val.keys(): val[key_.upper()] = val.pop(key_) elements.append(etree.Element(key.upper(), **val)) for element in elements: if element.tag == 'IPV6_ADDRESS': addr = element.attrib['VALUE'] if '/' in addr: addr, plen = addr.rsplit('/', 1) element.attrib.update({'VALUE': addr, 'PREFIXLEN': plen}) if 'PREFIXLEN' not in element.attrib: element.attrib['PREFIXLEN'] = '64' return self._control_tag('RIB_INFO', 'MOD_NETWORK_SETTINGS', elements=elements) mod_network_settings.requires_dict = ['static_route_1', 'static_route_2', 'static_route_3', 'ipv6_static_route_1', 'ipv6_static_route2', 'ipv6_static_route_3'] def mod_dir_config(self, dir_authentication_enabled=None, dir_local_user_acct=None,dir_server_address=None, dir_server_port=None,dir_object_dn=None,dir_object_password=None, dir_user_context_1=None,dir_user_context_2=None, dir_user_context_3=None,dir_user_context_4=None, dir_user_context_5=None,dir_user_context_6=None, dir_user_context_7=None,dir_user_context_8=None, dir_user_context_9=None,dir_user_context_10=None, dir_user_context_11=None,dir_user_context_12=None, dir_user_context_13=None,dir_user_context_14=None, dir_user_context_15=None,dir_enable_grp_acct=None, dir_kerberos_enabled=None,dir_kerberos_realm=None, dir_kerberos_kdc_address=None,dir_kerberos_kdc_port=None, dir_kerberos_keytab=None, dir_grpacct1_name=None,dir_grpacct1_sid=None, dir_grpacct1_priv=None,dir_grpacct2_name=None, dir_grpacct2_sid=None,dir_grpacct2_priv=None, dir_grpacct3_name=None,dir_grpacct3_sid=None, dir_grpacct3_priv=None,dir_grpacct4_name=None, dir_grpacct4_sid=None,dir_grpacct4_priv=None, dir_grpacct5_name=None,dir_grpacct5_sid=None, dir_grpacct5_priv=None,dir_grpacct6_name=None, dir_grpacct6_sid=None,dir_grpacct6_priv=None): """Modify iLO directory configuration, only values that are specified will be changed.""" vars = dict(locals()) del vars['self'] # create special case for element with text inside if dir_kerberos_keytab: keytab_el = etree.Element('DIR_KERBEROS_KEYTAB') keytab_el.text = dir_kerberos_keytab del vars['dir_kerberos_keytab'] elements = [etree.Element(x.upper(), VALUE=str({True: 'Yes', \ False: 'No'}.get(vars[x], vars[x]))) for x in vars if vars[x] is not None] if dir_kerberos_keytab: elements.append(keytab_el) return self._control_tag('DIR_INFO','MOD_DIR_CONFIG',elements=elements) def mod_snmp_im_settings(self, snmp_access=None, web_agent_ip_address=None, snmp_address_1=None, snmp_address_1_rocommunity=None, snmp_address_1_trapcommunity=None, snmp_address_2=None, snmp_address_2_rocommunity=None, snmp_address_2_trapcommunity=None, snmp_address_3=None, snmp_address_3_rocommunity=None, snmp_address_3_trapcommunity=None, snmp_port=None, snmp_trap_port=None, snmp_v3_engine_id=None, snmp_passthrough_status=None, trap_source_identifier=None, os_traps=None, rib_traps=None, cold_start_trap_broadcast=None, snmp_v1_traps=None, cim_security_mask=None, snmp_sys_location=None, snmp_sys_contact=None, agentless_management_enable=None, snmp_system_role=None, snmp_system_role_detail=None, snmp_user_profile_1=None, snmp_user_profile_2=None, snmp_user_profile_3=None): """Configure the SNMP and Insight Manager integration settings. The trapcommunity settings must be dicts with keys value (the name of the community) and version (1 or 2c)""" vars = dict(locals()) del vars['self'] elements = [etree.Element(x.upper(), VALUE=str({True: 'Yes', False: 'No'}.get(vars[x], vars[x]))) for x in vars if vars[x] is not None and 'trapcommunity' not in x and 'snmp_user_profile' not in x] for key in vars: if 'trapcommunity' in key and vars[key]: val = vars[key] for key_ in val.keys(): val[key_.upper()] = str(val.pop(key_)) elements.append(etree.Element(key.upper(), **val)) elif 'snmp_user_profile' in key and vars[key]: elt = etree.Element(key[:-2].upper(), {'INDEX': key[-1]}) for key, val in vars[key].items(): etree.SubElement(elt, key.upper(), VALUE=str(val)) elements.append(elt) return self._control_tag('RIB_INFO', 'MOD_SNMP_IM_SETTINGS', elements=elements) mod_snmp_im_settings.requires_dict = ['snmp_user_profile_1', 'snmp_user_profile_2', 'snmp_user_profile_3', 'snmp_address_1_trapcommunity', 'snmp_address_2_trapcommunity', 'snmp_address_3_trapcommunity'] def mod_sso_settings(self, trust_mode=None, user_remote_cons_priv=None, user_reset_server_priv=None, user_virtual_media_priv=None, user_config_ilo_priv=None, user_admin_priv=None, operator_login_priv=None, operator_remote_cons_priv=None, operator_reset_server_priv=None, operator_virtual_media_priv=None, operator_config_ilo_priv=None, operator_admin_priv=None, administrator_login_priv=None, administrator_remote_cons_priv=None, administrator_reset_server_priv=None, administrator_virtual_media_priv=None, administrator_config_ilo_priv=None, administrator_admin_priv=None): vars = dict(locals()) del vars['self'] del vars['trust_mode'] elements = [] if trust_mode is not None: elements.append(etree.Element('TRUST_MODE', attrib={'VALUE': trust_mode})) vars = [(x.upper().split('_', 1), {True: 'Yes', False: 'No'}.get(vars[x], vars[x])) for x in vars if vars[x]] elements += [etree.Element(x[0][0] + '_ROLE', attrib={x[0][1]: x[1]}) for x in vars] return self._control_tag('SSO_INFO', 'MOD_SSO_SETTINGS', elements=elements) def mod_user(self, user_login, user_name=None, password=None, admin_priv=None, remote_cons_priv=None, reset_server_priv=None, virtual_media_priv=None, config_ilo_priv=None): """Set attributes for a user, only specified arguments will be changed. All arguments except user_name and password should be boolean""" attrs = locals() elements = [] if attrs['user_name'] is not None: elements.append(etree.Element('USER_NAME', VALUE=attrs['user_name'])) if attrs['password'] is not None: elements.append(etree.Element('PASSWORD', VALUE=DoNotEscapeMe(attrs['password']))) for attribute in [x for x in attrs.keys() if x.endswith('_priv')]: if attrs[attribute] is not None: val = ['No', 'Yes'][bool(attrs[attribute])] elements.append(etree.Element(attribute.upper(), VALUE=val)) return self._control_tag('USER_INFO', 'MOD_USER', attrib={'USER_LOGIN': user_login}, elements=elements) def press_pwr_btn(self): """Press the power button""" return self._control_tag('SERVER_INFO', 'PRESS_PWR_BTN') def profile_apply(self, desc_name, action): """Apply a deployment profile""" elements = [ etree.Element('PROFILE_DESC_NAME', attrib={'VALUE': desc_name}), etree.Element('PROFILE_OPTIONS', attrib={'VALUE': 'none'}), # Currently unused etree.Element('PROFILE_ACTION', attrib={'VALUE': action}), ] return self._control_tag('RIB_INFO', 'PROFILE_APPLY', elements=elements) def profile_apply_get_results(self): """Retrieve the results of the last profile_apply""" return self._info_tag('RIB_INFO', 'PROFILE_APPLY_GET_RESULTS') def profile_delete(self, desc_name): """Delet the specified deployment profile""" return self._control_tag('RIB_INFO', 'PROFILE_DELETE', elements=[etree.Element('PROFILE_DESC_NAME', attrib={'VALUE': desc_name})]) def profile_desc_download(self, desc_name, name, description, blob_namespace=None, blob_name=None, url=None): """Make the iLO download a blob and create a deployment profile""" elements = [ etree.Element('PROFILE_DESC_NAME', attrib={'VALUE': desc_name}), etree.Element('PROFILE_NAME', attrib={'VALUE': name}), etree.Element('PROFILE_DESCRIPTION', attrib={'VALUE': description}), etree.Element('PROFILE_SCHEMA', attrib={'VALUE': 'intelligentprovisioning.1.0.0'}), ] if blob_namespace: elements.append(etree.Element('BLOB_NAMESPACE', attrs={'VALUE': blob_namespace})) if blob_name: elements.append(etree.Element('BLOB_NAME', attrs={'VALUE': blob_name})) if url: elements.append(etree.Element('PROFILE_URL', attrs={'VALUE': url})) return self._control_tag('RIB_INFO', 'PROFILE_DESC_DOWNLOAD', elements=elements) def profile_list(self): """List all profile descriptors""" def process(data): if isinstance(data, dict): return data.values() return data return self._info_tag('RIB_INFO', 'PROFILE_LIST', 'PROFILE_DESC_LIST', process=process) def hold_pwr_btn(self): """Press and hold the power button""" return self._control_tag('SERVER_INFO', 'HOLD_PWR_BTN') def cold_boot_server(self): """Force a cold boot of the server""" return self._control_tag('SERVER_INFO', 'COLD_BOOT_SERVER') def warm_boot_server(self): """Force a warm boot of the server""" return self._control_tag('SERVER_INFO', 'WARM_BOOT_SERVER') def reset_rib(self): """Reset the iLO/RILOE board""" return self._control_tag('RIB_INFO', 'RESET_RIB') def reset_server(self): """Power cycle the server""" return self._control_tag('SERVER_INFO', 'RESET_SERVER') def set_ahs_status(self, status): """Enable or disable AHS logging""" status = {True: 'enable', False: 'disable'}[status] return self._control_tag('RIB_INFO', 'SET_AHS_STATUS', attrib={'VALUE': status}) def set_asset_tag(self, asset_tag): """Set the server asset tag""" return self._control_tag('SERVER_INFO', 'SET_ASSET_TAG', attrib={'VALUE': asset_tag}) def set_ers_direct_connect(self, user_id, password, proxy_host=None, proxy_port=None, proxy_username=None, proxy_password=None): """Register your iLO with HP Insigt Online using Direct Connect. Note that you must also call dc_registration_complete""" elements = [ etree.Element('ERS_HPP_USER_ID', attrib={'VALUE': str(user_id)}), etree.Element('ERS_HPP_PASSWORD', attrib={'VALUE': str(password)}), ] for key, value in locals().items(): if key.startswith('proxy_') and value is not None: elements.append(etree.Element('ERS_WEB_' + key, attrib={'VALUE': str(value)})) return self._control_tag('RIB_INFO', 'SET_ERS_DIRECT_CONNECT', elements=elements) def set_ers_irs_connect(self, ers_destination_url, ers_destination_port): """Connect to an Insight Remote Support server""" elements = [ etree.Element('ERS_DESTINATION_URL', attrib={'VALUE': str(ers_destination_url)}), etree.Element('ERS_DESTINATION_PORT', attrib={'VALUE': str(ers_destination_port)}), ] return self._control_tag('RIB_INFO', 'SET_ERS_IRS_CONNECT', elements=elements) def set_ers_web_proxy(self, proxy_host, proxy_port, proxy_username=None, proxy_password=None): """Register your iLO with HP Insigt Online using Direct Connect. Note that you must also call dc_registration_complete""" elements = [] for key, value in locals().items(): if key.startswith('proxy_') and value is not None: elements.append(etree.Element('ERS_WEB_' + key, attrib={'VALUE': str(value)})) return self._control_tag('RIB_INFO', 'SET_ERS_WEB_PROXY', elements=elements) def set_federation_multicast(self, multicast_discovery_enabled=True, multicast_announcement_interval=600, ipv6_multicast_scope="Site", multicast_ttl=5): """Set the Federation multicast configuration""" multicast_discovery_enabled = {True: 'Yes', False: 'No'}[multicast_discovery_enabled] elements = [ etree.Element('MULTICAST_DISCOVERY_ENABLED', attrib={'VALUE': multicast_discovery_enabled}), etree.Element('MULTICAST_ANNOUNCEMENT_INTERVAL', attrib={'VALUE': str(multicast_announcement_interval)}), etree.Element('IPV6_MULTICAST_SCOPE', attrib={'VALUE': str(ipv6_multicast_scope)}), etree.Element('MULTICAST_TTL', attrib={'VALUE': str(multicast_ttl)}), ] return self._control_tag('RIB_INFO', 'SET_FEDERATION_MULTICAST', elements=elements) def set_language(self, lang_id): """Set the default language. Only EN, JA and ZH are supported""" return self._control_tag('RIB_INFO', 'SET_LANGUAGE', attrib={'LANG_ID': lang_id}) def set_host_power(self, host_power=True): """Turn host power on or off""" power = ['No', 'Yes'][bool(host_power)] return self._control_tag('SERVER_INFO', 'SET_HOST_POWER', attrib={'HOST_POWER': power}) def set_host_power_saver(self, host_power_saver): """Set the configuration of the ProLiant power regulator""" return self._control_tag('SERVER_INFO', 'SET_HOST_POWER_SAVER', attrib={'HOST_POWER_SAVER': str(host_power_saver)}) def set_one_time_boot(self, device): """Set one time boot device, device should be one of normal, floppy, cdrom, hdd, usb, rbsu or network. Ilo 4 also supports EMB-MENU (Displays the default boot menu), EMB-ACU (Boots into ACU), EMB-HPSUM-AUTO (Boots HPSUM in automatic update mode), EMB-DIAGS (Launches Insight Diagnostics for Linux in interactive mode) and RBSU (Boots into the system RBSU)""" if not device.lower().startswith('boot'): device = device.upper() return self._control_tag('SERVER_INFO', 'SET_ONE_TIME_BOOT', attrib={'VALUE': device}) def set_pending_boot_mode(self, boot_mode): """Set the boot mode for the next boot to UEFI or legacy""" return self._control_tag('SERVER_INFO', 'SET_PENDING_BOOT_MODE', attrib={'VALUE': boot_mode.upper()}) def set_persistent_boot(self, devices): """Set persistent boot order, devices should be comma-separated""" elements = [] if isinstance(devices, basestring): devices = devices.split(',') for device in devices: if not device.lower().startswith('boot'): device = device.upper() elements.append(etree.Element('DEVICE', VALUE=device)) return self._control_tag('SERVER_INFO', 'SET_PERSISTENT_BOOT', elements=elements) def set_pers_mouse_keyboard_enabled(self, enabled): """Enable/disable persistent mouse and keyboard""" enabled = {True: 'Yes', False: 'No'}.get(enabled,enabled) return self._control_tag('SERVER_INFO', 'SET_PERS_MOUSE_KEYBOARD_ENABLED', attrib={'VALUE': enabled}) def set_pwreg(self, type, threshold=None, duration=None): """Set the power alert threshold""" elements = [etree.Element('PWRALERT', TYPE=type)] if type.lower() != "disabled": elements.append(etree.Element('PWRALERT_SETTINGS', THRESHOLD=str(threshold), DURATION=str(duration))) return self._control_tag('SERVER_INFO', 'SET_PWREG', elements=elements) def set_power_cap(self, power_cap): """Set the power cap feature to a specific value""" return self._control_tag('SERVER_INFO', 'SET_POWER_CAP', attrib={'POWER_CAP': str(power_cap)}) def set_security_msg(self, security_msg, security_msg_text=''): """Enables/disables the security message on the iLO login screen and sets its value""" enabled = str({True: 'Yes', False: 'No'}.get(security_msg, security_msg)) text = etree.Element('SECURITY_MSG_TEXT') text.append(CDATA(security_msg_text)) elements = (etree.Element('SECURITY_MSG', VALUE=enabled), text) return self._control_tag('RIB_INFO', 'SET_SECURITY_MSG', elements=elements) def set_server_auto_pwr(self, setting): """Set the automatic power on delay setting. Valid settings are False, True (for minumum delay), 15, 30, 45 60 (for that amount of delay) or random (for a random delay of up to 60 seconds.)""" setting = str({True: 'Yes', False: 'No'}.get(setting, setting)) return self._control_tag('SERVER_INFO', 'SERVER_AUTO_PWR', attrib={'VALUE': setting}) def set_server_fqdn(self, fqdn): """Set the fqdn of the server""" return self._control_tag('SERVER_INFO', 'SERVER_FQDN', attrib={"VALUE": fqdn}) def set_server_name(self, name): """Set the name of the server""" try: return self._control_tag('SERVER_INFO', 'SERVER_NAME', attrib={"VALUE": name}) except IloError: # In their infinite wisdom, HP decided that only this tag should use value # instead of VALUE. And only for certain hardware/firmware combinations. # slowclap.mp3 return self._control_tag('SERVER_INFO', 'SERVER_NAME', attrib={"value": name}) def set_vf_status(self, boot_option="boot_once", write_protect=True): """Set the parameters of the RILOE virtual floppy specified virtual media. Valid boot options are boot_once, boot_always, no_boot, connect and disconnect.""" write_protect = ['NO', 'YES'][bool(write_protect)] elements = [ etree.Element('VF_BOOT_OPTION', value=boot_option.upper()), etree.Element('VF_WRITE_PROTECT', value=write_protect), ] return self._control_tag('RIB_INFO', 'SET_VF_STATUS', elements=elements) def set_vm_status(self, device="cdrom", boot_option="boot_once", write_protect=True): """Set the parameters of the specified virtual media. Valid boot options are boot_once, boot_always, no_boot, connect and disconnect. Valid devices are floppy and cdrom""" write_protect = ['NO', 'YES'][bool(write_protect)] elements = [ etree.Element('VM_BOOT_OPTION', value=boot_option.upper()), etree.Element('VM_WRITE_PROTECT', value=write_protect), ] return self._control_tag('RIB_INFO', 'SET_VM_STATUS', attrib={'DEVICE': device.upper()}, elements=elements) def trigger_l2_collection(self, message_id): """Initiate an L2 data collection submission to the Insight Remote Support server.""" element = etree.Element('MESSAGE_ID', attrib={'value': str(message_id)}) return self._control_tag('RIB_INFO', 'TRIGGER_L2_COLLECTION', elements=[element]) def trigger_test_event(self, message_id): """Trigger a test service event submission to the Insight Remote Support server.""" element = etree.Element('MESSAGE_ID', attrib={'value': str(message_id)}) return self._control_tag('RIB_INFO', 'TRIGGER_TEST_EVENT', elements=[element]) def uid_control(self, uid=False): """Turn the UID light on ("Yes") or off ("No")""" if isinstance(uid, basestring): uid = {'on': True, 'yes': True, 'off': False, 'no': False}.get(uid.lower(), uid) uid = ['No', 'Yes'][bool(uid)] return self._control_tag('SERVER_INFO', 'UID_CONTROL', attrib={"UID": uid.title()}) def update_rib_firmware(self, filename=None, version=None, progress=None): """Upload new RIB firmware, either specified by filename (.bin or .scexe) or version number. Use "latest" as version number to download and use the latest available firmware. API note: As this function may take a while, you can choose to receive progress messages by passing a callable in the progress parameter. This callable will be called many times to inform you about upload and flash progress.""" if self.delayed: raise IloError("Cannot run firmware update in delayed mode") if self.read_response: raise IloError("Cannot run firmware update in read_response mode") if not self.protocol: self._detect_protocol() # Backwards compatibility if filename == 'latest': version = 'latest' filename = None if filename and version: raise ValueError("Supply a filename or a version number, not both") if not (filename or version): raise ValueError("Supply a filename or a version number") current_version = self.get_fw_version() ilo = current_version['management_processor'].lower() if not filename: config = hpilo_fw.config(self.firmware_mirror) if version == 'latest': if ilo not in config: raise IloError("Cannot update %s to the latest version automatically" % ilo) version = config[ilo]['version'] iversion = '%s %s' % (ilo, version) if iversion not in config: raise ValueError("Unknown firmware version: %s" % version) if current_version['firmware_version'] >= version: return "Already up-to-date" hpilo_fw.download(iversion, progress=progress) filename = config[iversion]['file'] else: filename = hpilo_fw.parse(filename, ilo) fwlen = os.path.getsize(filename) root, inner = self._root_element('RIB_INFO', MODE='write') etree.SubElement(inner, 'TPM_ENABLED', VALUE='Yes') inner = etree.SubElement(inner, 'UPDATE_RIB_FIRMWARE', IMAGE_LOCATION=filename, IMAGE_LENGTH=str(fwlen)) if self.protocol == ILO_LOCAL: return self._request(root, progress)[1] elif self.protocol == ILO_RAW: inner.tail = '$EMBED:%s$' % filename return self._request(root, progress)[1] else: self._upload_file(filename, progress) return self._request(root, progress)[1] def xmldata(self, item='all'): """Get basic discovery data which all iLO versions expose over unauthenticated https. The default item to query is 'all'. Despite its name, it does not return all information. To get license information, use 'cpqkey' as argument.""" if self.delayed: raise IloError("xmldata is not compatible with delayed mode") if item.lower() not in ('all', 'cpqkey'): raise IloError("unsupported xmldata argument '%s', must be 'all' or 'cpqkey'" % item) if self.read_response: fd = open(self.read_response) data = fd.read() fd.close() else: url = 'https://%s:%s/xmldata?item=%s' % (self.hostname, self.port, item) if hasattr(ssl, 'create_default_context'): ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE opener = urllib2.build_opener(urllib2.ProxyHandler({}), urllib2.HTTPSHandler(context=ctx)) else: opener = urllib2.build_opener(urllib2.ProxyHandler({})) req = opener.open(url, None, self.timeout) data = req.read() self._debug(1, str(req.headers).rstrip() + "\n\n" + data.decode('utf-8', 'replace')) if self.save_response: fd = open(self.save_response, 'a') fd.write(data) fd.close() return self._element_children_to_dict(etree.fromstring(data)) def _parse_infra2_XXXX(self, element, key, ctag): ret = {key: []} for elt in element: tag = elt.tag.lower() if tag == 'bays': ret['bays'] = self._element_to_list(elt) elif tag == ctag: ret[key].append(self._element_children_to_dict(elt)) else: ret[tag] = elt.text return {key: ret} _parse_infra2_blades = lambda self, element: self._parse_infra2_XXXX(element, 'blades', 'blade') _parse_infra2_switches = lambda self, element: self._parse_infra2_XXXX(element, 'switches', 'switch') _parse_infra2_managers = lambda self, element: self._parse_infra2_XXXX(element, 'managers', 'manager') _parse_infra2_lcds = lambda self, element: self._parse_infra2_XXXX(element, 'lcds', 'lcd') _parse_infra2_fans = lambda self, element: self._parse_infra2_XXXX(element, 'fans', 'fan') def _parse_infra2_power(self, element): ret = self._parse_infra2_XXXX(element, 'power', 'powersupply') ret['power']['powersupply'] = ret['power'].pop('power') return ret def _parse_blade_portmap(self, element): ret = {'mezz': []} for elt in element: if elt.tag.lower() == 'mezz': ret['mezz'].append(self._element_children_to_dict(elt)) elif elt.tag.lower() == 'status': ret[elt.tag.lower()] = elt.text.strip() return {'portmap': ret} def _parse_mezz_slot(self, element): ret = {'port': []} for elt in element: if elt.tag.lower() == 'port': ret['port'].append(self._element_children_to_dict(elt)) elif elt.tag.lower() == 'type': ret[elt.tag.lower()] = elt.text.strip() return {'slot': ret} _parse_portmap_slot = _parse_mezz_slot def _parse_mezz_device(self, element): ret = {'port': []} for elt in element: if elt.tag.lower() == 'port': ret['port'].append(self._element_children_to_dict(elt)) else: ret[elt.tag.lower()] = elt.text.strip() return {'device': ret} def _parse_temps_temp(self, element): ret = {'thresholds': []} for elt in element: if elt.tag.lower() == 'threshold': ret['thresholds'].append(self._element_children_to_dict(elt)) else: ret[elt.tag.lower()] = elt.text return ret xmldata_ectd = { 'hsi': ('virtual',), 'bladesystem': ('manager',), 'infra2': ('diag', 'dim', 'vcm', 'vm'), 'blade': ('bay', 'diag', 'portmap', 'power', 'vmstat'), 'switch': ('bay', 'diag', 'portmap', 'power'), 'manager': ('bay', 'diag', 'power'), 'lcd': ('bay', 'diag'), 'fan': ('bay',), 'powersupply': ('bay', 'diag'), }