# machine.py # ========== import wmi import win32net import win32com.client from BeautifulSoup import BeautifulSoup from string import replace, digits, ascii_letters import urllib, urllib2 DELL_SVCTAG_URI = 'http://support.dell.com/support/topics/global.aspx/support/my_systems_info/en/details?c=us' DELL_SVCTAG_PARTS_URI = DELL_SVCTAG_URI + '&l=en&s=gen&~tab=2&~wsf=tabs' DELL_UA = [('User-Agent', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)')] class InvalidServiceTagException(Exception): pass def machines_in_default_domain(): domain_controller = win32net.NetGetDCName(None, None) domain_name = win32net.NetUserModalsGet(domain_controller, 2)['domain_name'] return machines_in_domain(domain_name) def machines_in_domain(domain_name): adsi = win32com.client.Dispatch("ADsNameSpaces") nt = adsi.GetObject('', 'WinNT:') result = nt.OpenDSObject('WinNT://%s' % domain_name, '', '', 0) result.Filter = ['computer'] for machine in result: yield machine.Name class Machine(object): def __init__(self, machine_name): self.machine = machine_name try: self.wmi_conn = wmi.WMI(self.machine) self.active = True except: self.active = False def __safe_encode(self, val): return ''.join([c for c in val if (c in digits or c in ascii_letters)]) @property def _enclosure(self): if not hasattr(self, '__enclosure_query'): self.__enclosure_query = self.wmi_conn.query('Select * from Win32_SystemEnclosure') return self.__enclosure_query @property def _system(self): if not hasattr(self, '__system_query'): self.__system_query = self.wmi_conn.query('Select * from Win32_ComputerSystem') return self.__system_query def query_results(self, query): return self.wmi_conn.query(query) @property def service_tags(self): tags = [self.__safe_encode(e.SerialNumber.strip()) for e in self._enclosure] if not tags: return None return tags @property def model(self): m = [self.__safe_encode(c.Model.strip()) for c in self._system] if not m: return None return m[0] @property def manufacturer(self): mfs = [self.__safe_encode(e.Manufacturer.strip()) for e in self._enclosure] if not mfs: return None return mfs[0] @property def name(self): return self.machine @property def is_dell(self): return 'dell' in self.manufacturer.lower() @property def has_valid_dell_service_tags(self): tag = self.service_tags[0] if len(tag) == 7: return True def __normalize_dell_charset(self, page_content): page_content = replace(page_content, " 0) for m in self.service_contracts]) return None # warranty_report.py import csv from machine import Machine, InvalidServiceTagException, machines_in_default_domain class MachineNotDell(Exception):pass class MachineNotActive(Exception):pass BASE_INDENT = 4 def validate_machine(m): """ We're only searching for Dell machines, so filter everything else out. """ if not m.active: raise MachineNotActive elif not m.is_dell: raise MachineNotDell else: return m def indent(spaces, text): return ' ' * BASE_INDENT + text def main(): output_writer = csv.writer(open('MachinesList.csv', 'w')) # write header output_writer.writerow([ 'Machine Name', 'Model', 'Service Tag(s)', 'Under Warranty?', 'Contract days remaining', ]) for hostname in machines_in_default_domain(): try: # Print Identification print 'Retrieving machine information for host: %s' % hostname m = validate_machine(Machine(hostname)) print indent(1, '%s (%s) discovered.' % (m.model, ', '.join(m.service_tags))) # Print Service Contracts print indent(1, 'Found %d service contracts:' % len(m.service_contracts)) for contract in m.service_contracts: print indent(2, '> %s (%d days remain)' % (contract['name'], contract['days_remaining'])) # Prettify (put newline after each record) print '' # Write Output to CSV output_writer.writerow([ hostname, m.model, ', '.join(m.service_tags), ['N','Y'][int(m.is_under_warranty)], max([c['days_remaining'] for c in m.service_contracts]) ]) # handle failures except MachineNotActive: print indent(1, 'No WMI response from %s. Continuing.\n' % hostname) continue except MachineNotDell: print indent(1, 'Machine was not manufactured by Dell. Continuing.\n') continue except InvalidServiceTagException: print indent(1, 'Machine provided an invalid service tag.') print indent(1, 'Unable to retrieve details. Continuing.\n') continue print 'Network scan complete.' if __name__ == '__main__': main()