Example #1
0
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)
Example #4
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)
Example #5
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)