def main(): """Scans through ZODB checking objects for dangling references""" execution_start = time.time() sys.path.append ("/opt/zenoss/Products/ZenModel") # From ZEN-12160 scriptName = os.path.basename(__file__).split('.')[0] parser = ZenToolboxUtils.parse_options(scriptVersion, scriptName + scriptSummary + documentationURL) # Add in any specific parser arguments for %scriptName cli_options = vars(parser.parse_args()) log, logFileName = ZenToolboxUtils.configure_logging(scriptName, scriptVersion, cli_options['tmpdir']) log.info("Command line options: %s" % (cli_options)) if cli_options['debug']: log.setLevel(logging.DEBUG) print "\n[%s] Initializing %s v%s (detailed log at %s)" % \ (time.strftime("%Y-%m-%d %H:%M:%S"), scriptName, scriptVersion, logFileName) # Attempt to get the zenoss.toolbox lock before any actions performed if not ZenToolboxUtils.get_lock("zenoss.toolbox", log): sys.exit(1) number_of_issues = ZenToolboxUtils.Counter(0) zodb_name = getGlobalConfiguration().get("zodb-db", "zodb") PKEReporter(zodb_name).run(log, number_of_issues) log.info("%d Dangling References were detected" % (number_of_issues.value())) print("[%s] Execution finished in %s\n" % (strftime("%Y-%m-%d %H:%M:%S", localtime()), datetime.timedelta(seconds=int(time.time() - execution_start)))) log.info("zodbscan completed in %1.2f seconds" % (time.time() - execution_start)) log.info("############################################################") if (number_of_issues.value() > 0): print("** WARNING ** Dangling Reference(s) were detected - Consult KB article at") print(" https://support.zenoss.com/hc/en-us/articles/203118175\n") sys.exit(1) else: sys.exit(0)
def global_catalog_paths_to_uids(catalogObject, fix, dmd, log, createEvents): """Scan through global_catalog verifying consistency of rids""" catalogReference = eval(catalogObject.dmdPath)._catalog catalogObject.initialSize = len(catalogReference.paths) if (catalogObject.initialSize > 50): progressBarChunkSize = (catalogObject.initialSize // 50) + 1 else: progressBarChunkSize = 1 log.info( "Examining global_catalog._catalog.paths for consistency against ._catalog.uids" ) print("[%s] Examining %-35s (%d Objects)" % (time.strftime("%Y-%m-%d %H:%M:%S"), "global_catalog 'paths to uids'", catalogObject.initialSize)) currentCycle = 0 while (currentCycle < maxCycles): currentCycle += 1 catalogObject.runResults[currentCycle] = { 'itemCount': ZenToolboxUtils.Counter(0), 'errorCount': ZenToolboxUtils.Counter(0), 'repairCount': ZenToolboxUtils.Counter(0) } log.info("Beginning cycle %d for global_catalog 'paths to uids'" % (currentCycle)) scan_progress_message(False, fix, currentCycle, "global_catalog 'paths to uids'", 0, 0, log) try: broken_rids = [] for rid, path in catalogReference.paths.iteritems(): catalogObject.runResults[currentCycle]['itemCount'].increment() if (catalogObject.runResults[currentCycle] ['itemCount'].value() % progressBarChunkSize) == 0: chunkNumber = catalogObject.runResults[currentCycle][ 'itemCount'].value() // progressBarChunkSize scan_progress_message( False, fix, currentCycle, "global_catalog 'paths to uids'", catalogObject.runResults[currentCycle] ['errorCount'].value(), chunkNumber, log) if path not in catalogReference.uids: catalogObject.runResults[currentCycle][ 'errorCount'].increment() broken_rids.append(rid) except Exception, e: log.exception(e) scan_progress_message( True, fix, currentCycle, "global_catalog 'paths to uids' consistency", catalogObject.runResults[currentCycle]['errorCount'].value(), chunkNumber, log) if fix: if catalogObject.runResults[currentCycle]['errorCount'].value( ) > 0: log.info("Attempting to repair %d detected issues", len(broken_rids)) for item in broken_rids: try: catalogObject.runResults[currentCycle][ 'repairCount'].increment() catalogReference.paths.pop(item) catalogReference.data.pop(item) catalogReference._p_changed = True transaction.commit() except: pass else: break if currentCycle > 1: if catalogObject.runResults[currentCycle]['errorCount'].value( ) == catalogObject.runResults[currentCycle - 1]['errorCount'].value(): break # Final transaction.abort() to try and free up used memory log.debug("Calling transaction.abort() to minimize memory footprint") transaction.abort()
def scan_catalog(catalogObject, fix, dmd, log, createEvents): """Scan through a catalog looking for broken references""" # Fix for ZEN-14717 (only for global_catalog) if (catalogObject.prettyName == 'global_catalog'): global_catalog_paths_to_uids(catalogObject, fix, dmd, log, createEvents) catalog = eval(catalogObject.dmdPath) catalogObject.initialSize = len(catalog) print("[%s] Examining %-35s (%d Objects)" % (time.strftime("%Y-%m-%d %H:%M:%S"), catalogObject.prettyName, catalogObject.initialSize)) log.info("Examining %s catalog with %d objects" % (catalogObject.prettyName, catalogObject.initialSize)) currentCycle = 0 while (currentCycle < maxCycles): currentCycle += 1 catalogObject.runResults[currentCycle] = { 'itemCount': ZenToolboxUtils.Counter(0), 'errorCount': ZenToolboxUtils.Counter(0), 'repairCount': ZenToolboxUtils.Counter(0) } log.info("Beginning cycle %d for catalog %s" % (currentCycle, catalogObject.prettyName)) scan_progress_message(False, fix, currentCycle, catalogObject.prettyName, 0, 0, log) try: brains = eval(catalogObject.dmdPath)() except Exception: raise catalogSize = len(brains) if (catalogSize > 50): progressBarChunkSize = (catalogSize // 50) + 1 else: progressBarChunkSize = 1 for brain in brains: catalogObject.runResults[currentCycle]['itemCount'].increment() if (catalogObject.runResults[currentCycle]['itemCount'].value() % progressBarChunkSize) == 0: chunkNumber = catalogObject.runResults[currentCycle][ 'itemCount'].value() // progressBarChunkSize scan_progress_message( False, fix, currentCycle, catalogObject.prettyName, catalogObject.runResults[currentCycle] ['errorCount'].value(), chunkNumber, log) try: testReference = brain.getObject() testReference._p_deactivate() except Exception: catalogObject.runResults[currentCycle]['errorCount'].increment( ) objectPathString = brain.getPath() log.error("Catalog %s contains broken object %s" % (catalogObject.prettyName, objectPathString)) if fix: log.info("Attempting to uncatalog %s" % (objectPathString)) try: catalogObject.runResults[currentCycle][ 'repairCount'].increment() transact(catalog.uncatalog_object)(objectPathString) except Exception as e: log.exception(e) # Final transaction.abort() to try and free up used memory log.debug("Calling transaction.abort() to minimize memory footprint") transaction.abort() scan_progress_message( True, fix, currentCycle, catalogObject.prettyName, catalogObject.runResults[currentCycle]['errorCount'].value(), chunkNumber, log) if fix: if catalogObject.runResults[currentCycle]['errorCount'].value( ) == 0: break if currentCycle > 1: if catalogObject.runResults[currentCycle]['errorCount'].value( ) == catalogObject.runResults[currentCycle - 1]['errorCount'].value(): break if createEvents: scriptName = os.path.basename(__file__).split('.')[0] eventMsg = "" for cycleID in catalogObject.runResults.keys(): eventMsg += "Cycle %d scanned %d items, found %d errors and attempted %d repairs\n" % \ (cycleID, catalogObject.runResults[cycleID]['itemCount'].value(), catalogObject.runResults[cycleID]['errorCount'].value(), catalogObject.runResults[cycleID]['repairCount'].value()) if not catalogObject.runResults[currentCycle]['errorCount'].value(): eventSeverity = 1 if currentCycle == 1: eventSummaryMsg = "'%s' - No Errors Detected (%d total items)" % \ (catalogObject.prettyName, catalogObject.initialSize) else: eventSummaryMsg = "'%s' - No Errors Detected [--fix was successful] (%d total items)" % \ (catalogObject.prettyName, catalogObject.initialSize) else: eventSeverity = 4 if fix: eventSummaryMsg = "'%s' - %d Errors Remain after --fix [consult log file] (%d total items)" % \ (catalogObject.prettyName, catalogObject.runResults[currentCycle]['errorCount'].value(), catalogObject.initialSize) else: eventSummaryMsg = "'%s' - %d Errors Detected [run with --fix] (%d total items)" % \ (catalogObject.prettyName, catalogObject.runResults[currentCycle]['errorCount'].value(), catalogObject.initialSize) log.debug("Creating event with %s, %s" % (eventSummaryMsg, eventSeverity)) ZenToolboxUtils.send_summary_event(eventSummaryMsg, eventSeverity, scriptName, catalogObject.prettyName, documentationURL, dmd, eventMsg) return (catalogObject.runResults[currentCycle]['errorCount'].value() != 0)
def main(): """ Scans through zodb hierarchy (from user-supplied path, defaults to /, checking for PKEs """ execution_start = time.time() scriptName = os.path.basename(__file__).split('.')[0] parser = ZenToolboxUtils.parse_options( scriptVersion, scriptName + scriptSummary + documentationURL) # Add in any specific parser arguments for %scriptName parser.add_argument("-f", "--fix", action="store_true", default=False, help="attempt to fix ZenRelationship objects") parser.add_argument("-n", "--cycles", action="store", default="2", type=int, help="maximum times to cycle (with --fix)") parser.add_argument("-p", "--path", action="store", default="/", type=str, help="base path to scan from (Devices.Server)?") parser.add_argument( "-u", "--unlimitedram", action="store_true", default=False, help="skip transaction.abort() - unbounded RAM, ~40%% faster") cli_options = vars(parser.parse_args()) log, logFileName = ZenToolboxUtils.configure_logging( scriptName, scriptVersion, cli_options['tmpdir']) log.info("Command line options: %s" % (cli_options)) if cli_options['debug']: log.setLevel(logging.DEBUG) print "\n[%s] Initializing %s v%s (detailed log at %s)" % \ (time.strftime("%Y-%m-%d %H:%M:%S"), scriptName, scriptVersion, logFileName) # Attempt to get the zenoss.toolbox lock before any actions performed if not ZenToolboxUtils.get_lock("zenoss.toolbox", log): sys.exit(1) # Obtain dmd ZenScriptBase connection dmd = ZenScriptBase(noopts=True, connect=True).dmd log.debug("ZenScriptBase connection obtained") counters = { 'item_count': ZenToolboxUtils.Counter(0), 'error_count': ZenToolboxUtils.Counter(0), 'repair_count': ZenToolboxUtils.Counter(0) } processed_path = re.split("[./]", cli_options['path']) if processed_path[0] == "app": processed_path = processed_path[1:] processed_path = '/'.join(processed_path) if processed_path else '/' try: folder = dmd.getObjByPath(processed_path) except KeyError: print "Invalid path: %s" % (cli_options['path']) else: print("[%s] Examining items under the '%s' path (%s):" % (strftime( "%Y-%m-%d %H:%M:%S", localtime()), cli_options['path'], folder)) log.info("Examining items under the '%s' path (%s)", cli_options['path'], folder) findPOSKeyErrors(folder, cli_options['fix'], cli_options['unlimitedram'], dmd, log, counters, cli_options['cycles']) print print("\n[%s] Execution finished in %s\n" % (strftime("%Y-%m-%d %H:%M:%S", localtime()), datetime.timedelta(seconds=int(time.time() - execution_start)))) log.info("findposkeyerror completed in %1.2f seconds", time.time() - execution_start) log.info("############################################################") if not cli_options['skipEvents']: if counters['error_count'].value(): eventSeverity = 4 eventSummaryMsg = "%s encountered %d errors (took %1.2f seconds)" % \ (scriptName, counters['error_count'].value(), (time.time() - execution_start)) else: eventSeverity = 2 eventSummaryMsg = "%s completed without errors (took %1.2f seconds)" % \ (scriptName, (time.time() - execution_start)) ZenToolboxUtils.send_summary_event(eventSummaryMsg, eventSeverity, scriptName, "executionStatus", documentationURL, dmd) if ((counters['error_count'].value() > 0) and not cli_options['fix']): print("** WARNING ** Issues were detected - Consult KB article at") print(" https://support.zenoss.com/hc/en-us/articles/203117795\n") sys.exit(1) else: sys.exit(0)
def main(): '''Scans zodb objects for ZenRelations issues. If --fix, attempts repair.''' execution_start = time.time() scriptName = os.path.basename(__file__).split('.')[0] parser = ZenToolboxUtils.parse_options(scriptVersion, scriptName + scriptSummary + documentationURL) # Add in any specific parser arguments for %scriptName parser.add_argument("-f", "--fix", action="store_true", default=False, help="attempt to remove any invalid references") parser.add_argument("-n", "--cycles", action="store", default="2", type=int, help="maximum times to cycle (with --fix)") parser.add_argument("-u", "--unlimitedram", action="store_true", default=False, help="skip transaction.abort() - unbounded RAM, ~40%% faster") cli_options = vars(parser.parse_args()) log, logFileName = ZenToolboxUtils.configure_logging(scriptName, scriptVersion, cli_options['tmpdir']) log.info("Command line options: %s" % (cli_options)) if cli_options['debug']: log.setLevel(logging.DEBUG) print "\n[%s] Initializing %s v%s (detailed log at %s)" % \ (time.strftime("%Y-%m-%d %H:%M:%S"), scriptName, scriptVersion, logFileName) # Attempt to get the zenoss.toolbox lock before any actions performed if not ZenToolboxUtils.get_lock("zenoss.toolbox", log): sys.exit(1) # Obtain dmd ZenScriptBase connection dmd = ZenScriptBase(noopts=True, connect=True).dmd log.debug("ZenScriptBase connection obtained") counters = { 'item_count': ZenToolboxUtils.Counter(0), 'error_count': ZenToolboxUtils.Counter(0), 'repair_count': ZenToolboxUtils.Counter(0) } scan_relationships(cli_options['fix'], cli_options['cycles'], cli_options['unlimitedram'], dmd, log, counters) if not cli_options['skipEvents']: if counters['error_count'].value(): eventSeverity = 4 eventSummaryMsg = "%s encountered %d errors (took %1.2f seconds)" % \ (scriptName, counters['error_count'].value(), (time.time() - execution_start)) else: eventSeverity = 2 eventSummaryMsg = "%s completed without errors (took %1.2f seconds)" % \ (scriptName, (time.time() - execution_start)) ZenToolboxUtils.send_summary_event( eventSummaryMsg, eventSeverity, scriptName, "executionStatus", documentationURL, dmd ) # Print final status summary, update log file with termination block log.info("zenrelationscan examined %d objects, encountered %d errors, and attempted %d repairs", counters['item_count'].value(), counters['error_count'].value(), counters['repair_count'].value()) print("\n[%s] Execution finished in %s\n" % (strftime("%Y-%m-%d %H:%M:%S", localtime()), datetime.timedelta(seconds=int(time.time() - execution_start)))) log.info("zenrelationscan completed in %1.2f seconds" % (time.time() - execution_start)) log.info("############################################################") if ((counters['error_count'].value() > 0) and not cli_options['fix']): print("** WARNING ** Issues were detected - Consult KB article at") print(" https://support.zenoss.com/hc/en-us/articles/203121165\n") sys.exit(1) else: sys.exit(0)