def _snmp_lldp(ip_address, snmp_community, snmp_version, messages=[]): try: interfaces_map = _get_device_interfaces_map(ip_address, snmp_community, snmp_version) mac_addresses_map = _get_remote_mac_addresses_map( ip_address, snmp_community, snmp_version) ip_addresses_map = _get_remote_ip_addresses_map( ip_address, snmp_community, snmp_version) ports_map = _get_remote_connected_ports_map(ip_address, snmp_community, snmp_version) except TypeError: raise Error("No answer.") except IndexError: raise Error("Incorrect answer.") connections = [] for item_id, mac_address in mac_addresses_map.iteritems(): connection = { 'connection_type': ConnectionType.network.name, 'connected_device_mac_addresses': mac_address } connected_ip = ip_addresses_map.get(item_id) if connected_ip: connection['connected_device_ip_addresses'] = connected_ip details = {} outbound_port = interfaces_map.get(item_id) if outbound_port: details['outbound_port'] = outbound_port inbound_port = ports_map.get(item_id) if inbound_port: details['inbound_port'] = inbound_port if details: connection['details'] = details connections.append(connection) return {'system_ip_addresses': [ip_address], 'connections': connections}
def _send_soap(post_url, login, password, message): """Try to send soap message to post_url using http basic authentication. Note, that we don't store any session information, nor validate ssl certificate. Any following requests will re-send basic auth header again. """ r = requests.post( post_url, data=message, auth=(login, password), verify=False, headers={ 'Content-Type': 'application/soap+xml;charset=UTF-8', }, ) if not r.ok: if r.status_code == 401: raise Error("Invalid username or password.") raise Error( "SoapError: Reponse was: %s\nRequest was:%s" % (r.text, message), ) # soap, how I hate you... # sometimes errors are embedded INSIDE the envelope BUT response code is OK # in this case, try to detect these errors as well. errors_path = '{s}Body/{s}Fault'.format(s=XMLNS_S) errors_list = [] errors_node = ET.XML(r.text).find(errors_path) if errors_node: errors_list = [node_text for node_text in errors_node.itertext()] raise Error('SoapError: Request was:%s, Response errors were:%s' % (message, ','.join(errors_list))) # return raw xml data... return r.text
def command(self, command, subcommand, *args): command = [ 'ipmitool', '-H', self.host, '-U', self.user, '-P', self.password, command, subcommand, ] if args: command.extend(args) proc = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) out, err = proc.communicate() if proc.returncode and err: if err.lower().startswith('invalid user name'): raise AuthError('Invalid user name.') raise Error('Error calling ipmitool: %s' % err) return force_unicode(out)
def _ipmi(ipmitool): try: fru = _get_ipmi_fru(ipmitool) except AuthError: ipmitool = IPMITool(ipmitool.host, 'ADMIN') try: fru = _get_ipmi_fru(ipmitool) except AuthError: ipmitool = IPMITool(ipmitool.host, 'ADMIN', 'ADMIN') fru = _get_ipmi_fru(ipmitool) top = fru['/SYS'] if not top: top = fru['Builtin FRU Device'] if not top: raise Error('Incompatible answer.') device_info = _get_base_info(top) mac_addresses = _get_mac_addresses(ipmitool, fru) if mac_addresses: device_info['mac_addresses'] = mac_addresses processors, memory = _get_components(fru) if processors: device_info['processors'] = processors if memory: device_info['memory'] = memory device_info['management_ip_addresses'] = [ipmitool.host] return device_info
def _get_base_info(idrac): tree = idrac.run_command('DCIM_SystemView') xmlns_n1 = XMLNS_N1_BASE % "DCIM_SystemView" q = "{}Body/{}EnumerateResponse/{}Items/{}DCIM_SystemView".format( XMLNS_S, XMLNS_WSEN, XMLNS_WSMAN, xmlns_n1, ) records = tree.findall(q) if not records: raise Error("Incorrect answer in the _get_base_info.") result = { 'model_name': "{} {}".format( records[0].find("{}{}".format( xmlns_n1, 'Manufacturer'), ).text.strip().replace(" Inc.", ""), records[0].find("{}{}".format(xmlns_n1, 'Model'), ).text.strip(), ), } serial_number = records[0].find( "{}{}".format(xmlns_n1, 'ChassisServiceTag'), ).text.strip() if serial_number not in SERIAL_BLACKLIST: result['serial_number'] = serial_number return result
def _get_code(response, regexp): lines = [] for line in response.readlines(): line = line.strip() if not line or line.startswith('//'): continue lines.append(line) response = ''.join(lines) m = regexp.search(response) if not m: raise Error('No match.') return m.group(1)
def _get_all_facts_by_hostnames(self, hostnames): founds = [] for hostname in hostnames: found_data = self._get_data_for_hostname(hostname) if found_data: founds.append(found_data) if len(founds) > 1: raise Error( "More than 1 machine found by puppetdb API for " "this hostname set: {}".format(', '.join(hostnames)), ) facts = founds[0] if len(founds) == 1 else None return facts
def _puppet(ip_address, messages=[]): ''' Similar to ``_puppet`` function, but it gets data from first resolved provider (provider also MUST return data), instead of passed provider (as param) like ``_puppet`` do. ''' ip_addresses_set, hostnames_set = _get_ip_addresses_hostnames_sets( ip_address, ) providers_chain = get_puppet_providers() for provider in providers_chain: facts = provider.get_facts(ip_addresses_set, hostnames_set, messages) if facts: break else: msg = "Could not find facts for ip address: {}".format(ip_address) raise Error(msg) is_virtual = _is_host_virtual(facts) if 'lshw' in facts: device_info = _parse_lshw(facts['lshw'], is_virtual) else: device_info = _parse_facts(facts, is_virtual) ip_addresses = handle_facts_ip_addresses(facts) if ip_addresses: device_info['system_ip_addresses'] = ip_addresses else: device_info['system_ip_addresses'] = [ip_address] disk_shares = handle_facts_wwn(facts) if disk_shares: device_info['disk_shares'] = disk_shares disks = device_info.get('disks', []) disks = _merge_disks_results( disks, handle_facts_3ware_disks(facts), ) disks = _merge_disks_results( disks, handle_facts_smartctl(facts), ) disks = _merge_disks_results( disks, handle_facts_hpacu(facts), ) disks = _merge_disks_results( disks, handle_facts_megaraid(facts), ) device_info['disks'] = disks installed_software = handle_facts_packages(facts) if installed_software: device_info['installed_software'] = installed_software device_info.update(handle_facts_os(facts, is_virtual)) return device_info
def parse_lshw(raw_data): parser = ET.ETCompatXMLParser(recover=True) response = ET.fromstring(raw_data, parser=parser) if response.tag and response.tag.upper() == 'LIST': response = response[0] elif response.tag and response.tag.upper() == 'NODE': pass else: raise Error('Lshw parse error.') for element in response.findall('.//'): for k in element.attrib.keys(): try: v = element.attrib[k] except UnicodeDecodeError: continue # value has bytes not possible to decode with UTF-8 if (element.tag, k) in TAG_TRANSLATION_PAIRS: try: element.tag = v except ValueError: pass continue if (element.tag, k) in TEXT_TRANSLATION_PAIRS: element.text = v continue if k == 'units': value = ET.Element(b'value') value.text = element.text element.text = '' element.append(value) child = ET.Element(k) child.text = v element.append(child) return nullify( etree_to_dict( response, _converters=[ _nullify, int, float, lck.xml.converters._datetime, lck.xml.converters._datetime_strip_tz, ], ), )[1]
def _puppet(provider, ip_address, messages=[]): ip_addresses_set, hostnames_set = _get_ip_addresses_hostnames_sets( ip_address, ) facts = provider.get_facts(ip_addresses_set, hostnames_set, messages) if not facts: raise Error('Host config not found.') is_virtual = _is_host_virtual(facts) if 'lshw' in facts: device_info = _parse_lshw(facts['lshw'], is_virtual) else: device_info = _parse_facts(facts, is_virtual) ip_addresses = handle_facts_ip_addresses(facts) if ip_addresses: device_info['system_ip_addresses'] = ip_addresses else: device_info['system_ip_addresses'] = [ip_address] disk_shares = handle_facts_wwn(facts) if disk_shares: device_info['disk_shares'] = disk_shares disks = device_info.get('disks', []) disks = _merge_disks_results( disks, handle_facts_3ware_disks(facts), ) disks = _merge_disks_results( disks, handle_facts_smartctl(facts), ) disks = _merge_disks_results( disks, handle_facts_hpacu(facts), ) disks = _merge_disks_results( disks, handle_facts_megaraid(facts), ) device_info['disks'] = disks installed_software = handle_facts_packages(facts) if installed_software: device_info['installed_software'] = installed_software device_info.update(handle_facts_os(facts, is_virtual)) return device_info
def _get_facts_by_hostnames(self, hostnames): facts = None for hostname in hostnames: rows = self.conn.execute( """ SELECT fn.name, fv.value FROM hosts h, fact_values fv, fact_names fn WHERE h.name=%s AND fv.host_id=h.id AND fv.fact_name_id=fn.id """, hostname, ) _facts = dict(rows.fetchall()) if _facts: if not facts: facts = _facts else: raise Error( "More than 1 machine reported by Puppet for " "this hostname set: {}".format(', '.join(hostnames)), ) return facts
def _get_facts_by_ip_addresses(self, ip_addresses): facts = None for ip_address in ip_addresses: rows = self.conn.execute( """ SELECT fn.name, fv.value FROM hosts h, fact_values fv, fact_names fn WHERE h.ip=%s AND fv.host_id=h.id AND fv.fact_name_id=fn.id """, ip_address, ) _facts = dict(rows.fetchall()) if _facts: if _facts['virtual'] == 'zone': continue if not facts: facts = _facts else: raise Error( "More than 1 machine reported by Puppet for " "this IP set: {}".format(', '.join(ip_addresses)), ) return facts
def _ssh_xen(ssh, ip_address): sudo_mode = _enable_sudo_mode(ssh) uuid = _get_current_host_uuid(ssh, ip_address, sudo_mode) if not uuid: raise Error('Could not find this host UUID.') vms = _get_running_vms(ssh, uuid, sudo_mode) macs = _get_macs(ssh, sudo_mode) disks = _get_disks(ssh, sudo_mode) shares = get_disk_shares(ssh, include_logical_volumes=True) device_info = { 'subdevices': [], 'type': DeviceType.unknown.raw, 'system_ip_addresses': [ip_address], } for vm_name, vm_uuid, vm_cores, vm_memory in vms: vm_device = { 'model_name': 'XEN Virtual Server', } vm_device['mac_addresses'] = [ MACAddressField.normalize(mac) for i, mac in enumerate(macs.get(vm_name, [])) ] vm_device['serial_number'] = vm_uuid vm_device['hostname'] = vm_name vm_device['processors'] = [{ 'family': 'XEN Virtual', 'name': 'XEN Virtual CPU', 'label': 'CPU %d' % i, 'model_name': 'XEN Virtual', 'cores': 1, 'index': i, } for i in xrange(vm_cores)] vm_device['memory'] = [ { 'family': 'Virtual', 'size': vm_memory, 'label': 'XEN Virtual', }, ] vm_disks = disks.get(vm_name, []) for uuid, sr_uuid, size, device in vm_disks: wwn, mount_size = shares.get('VHD-%s' % uuid, (None, None)) if wwn: share = { 'serial_number': wwn, 'is_virtual': True, 'size': mount_size, 'volume': device, } if 'disk_shares' not in vm_device: vm_device['disk_shares'] = [] vm_device['disk_shares'].append(share) else: storage = { 'size': size, 'label': device, 'family': 'XEN Virtual Disk', } if 'disks' not in vm_device: vm_device['disks'] = [] vm_device['disks'].append(storage) device_info['subdevices'].append(vm_device) return device_info