Exemple #1
0
    def go(driver):
        from Products.ZenUtils.ZenScriptBase import ZenScriptBase
        from ZenPacks.zenoss.ZenMailTx.MailTxConfigService import MailTxConfigService

        zendmd = ZenScriptBase(noopts=True, connect=True)
        dmd = zendmd.dmd
        d = dmd.Devices.findDevice(device)
        if not d:
            sys.stderr.write("Unable to find device %s\n" % device)
            sys.exit(1)
        log.setLevel(logging.DEBUG)
        service = MailTxConfigService(dmd, d.perfServer().id)
        if not service:
            sys.stderr.write("Unable to find configuration for %s" % device)
        proxy = service.remote_getDeviceConfigs([device])
        if proxy:
            proxy = proxy[0]
        else:
            raise ValueError(
                "Unable to find a valid MailTx config for device %s" % device)
        config = proxy.datasources
        if datasource:
            config = [c for c in proxy.datasources if c.name == datasource]
        if not config:
            raise ValueError(
                "Unable to find a MailTx config %s for device %s" %
                (datasource or '', device))
        config = config[0]
        config.ignoreIds = set()
        now = time.time()
        yield sendMessage(config)
        log.debug("Result of message send: %s", driver.next())
        yield getMessage(config, 5.0)
        log.debug("Result of message fetch: %s", driver.next())
        log.info("Message delivered in %.2f seconds" % (time.time() - now))
Exemple #2
0
def getmysqlcreds():
    """Fetch the mysql creds from the object database and store them
    in the global file for use in later commands.

    returns True on success, False on failure
    """
    pids = os.popen('pgrep -f zeo.py').read().split('\n')
    pids = [int(p) for p in pids if p]
    if len(pids) < 1:
        log.warning('zeo is not running')
        return False
    log.debug("Fetching mysql credentials")
    print "Fetching mysql credentials"
    mysqlpass = '******'
    mysqluser = '******'
    mysqlport = '3306'
    mysqlhost = 'localhost'
    sys.path.insert(0, os.path.join(zenhome, 'lib/python'))
    try:
        import Globals
        from Products.ZenUtils.ZenScriptBase import ZenScriptBase
        zsb = ZenScriptBase(noopts=True, connect=True)
        zsb.getDataRoot()
        dmd = zsb.dmd
        mysqlpass = dmd.ZenEventManager.password
        mysqluser = dmd.ZenEventManager.username
        mysqlport = dmd.ZenEventManager.port
        mysqlhost = dmd.ZenEventManager.host
    except Exception, ex:
        log.exception("Unable to open the object database for "
                      "mysql credentials")
        pass
Exemple #3
0
def get_device_properties(slots):
    """Retrieve device attributes from Zenoss and store in local data structure (slots).
"""
    dmd = ZenScriptBase(connect=True).dmd
    for device in dmd.Devices.getSubDevices():
        groups = device.getDeviceGroupNames()
        for a in range(0, len(groups)):
            if groups[a].find(groupName) != -1:
                slot = device.rackSlot
                slotWords = (str(slot)).split()
                slotNum = int(slotWords[len(slotWords) - 1])
                serialNum = device.getHWSerialNumber()
                name = device.getDeviceName()
                ip = device.getManageIp()
                classPath = device.getDeviceClassPath()
                classPath.strip()
                classes = classPath.split('/')
                className = classes[len(classes) - 1]

                # NOTE: Temporary hack to accommodate 1900
                if slotNum == 1:
                    if name.find("ZX1900BaseDevice") != -1:
                        slotNum = 2

                # Store info in slots
                slotInfo = slots[slotNum]
                slotInfo['ip'] = ip
                slotInfo['name'] = name
                slotInfo['serial'] = serialNum
                slotInfo['class'] = className
def main():
    """Scans catalogs, reindexes if needed, and prints a summary"""
    cmdLineOptions = parse_options()
    dmd = ZenScriptBase(noopts=True, connect=True).dmd
    catalogList = [
        dmd.global_catalog,
        dmd.Networks.ipSearch,
        dmd.IPv6Networks.ipSearch,
        dmd.Devices.deviceSearch,
        dmd.Services.serviceSearch,
        dmd.ZenLinkManager.layer2_catalog,
        dmd.ZenLinkManager.layer3_catalog,
        dmd.maintenanceWindowSearch,
        dmd.zenPackPersistence,
        dmd.Manufacturers.productSearch
        ]

    for catalog in catalogList:
        scan_catalog(catalog, cmdLineOptions['fix'])

    if cmdLineOptions['fix']:
        print ""
        print "Reindexing dmd Objects..."
        try:
            dmd.Devices.reIndex()
            dmd.Events.reIndex()
            dmd.Manufacturers.reIndex()
            dmd.Networks.reIndex()
        except Exception, e:
            summaryMsg.append("")
            summaryMsg.append(" ** Exception encountered when reindexing dmd object %s"
                              % (e))
Exemple #5
0
def set_device_properties(slots):
    """Use local data structure (slots) to set device attributes in Zenoss.
"""
    # Set serial number, slot & name.
    # Zenoss will overwrite serial number & slot for Znyx devices.
    # So, only set these values for ZXSBC devices.
    # NOTE: Add error handling & logging.

    dmd = ZenScriptBase(connect=True).dmd

    for device in dmd.Devices.getSubDevices():
        for slotNum in range(0, len(slots)):
            slotInfo = slots[slotNum]

            # Skip empty slots
            if slotInfo['serial'] == None:
                continue

            if slotInfo['ip'] == device.getManageIp():
                #if device.id != device.getDeviceName():
                device.renameDevice(slotInfo['name'])
                manf = device.getOSManufacturerName()
                if not manf.find("Znyx") != -1:
                    device.setHWSerialNumber(slotInfo['serial'])
                    device.rackSlot = slotNum

    dmd.Devices.reIndex()
    commit()
Exemple #6
0
def main():
    '''Performs reindex call on different DMD categories (used to be a part of zencatalogscan)'''

    execution_start = time.time()
    cli_options = parse_options()
    log = configure_logging('zenindextool')
    log.info("Command line options: %s" % (cli_options))
    if cli_options['debug']:
        log.setLevel(logging.DEBUG)

    # Attempt to get the zenoss.toolbox lock before any actions performed
    if not get_lock("zenoss.toolbox", log):
        sys.exit(1)

    # Obtain dmd ZenScriptBase connection
    dmd = ZenScriptBase(noopts=True, connect=True).dmd
    log.debug("ZenScriptBase connection obtained")

    any_issue = False

    # Else build list of catalogs, then process catalog(s) and perform reindex if --fix
    types_to_reIndex = {
        'Devices': 'dmd.Devices',
        'Events': 'dmd.Events',
        'Manufacturers': 'dmd.Manufacturers',
        'Networks': 'dmd.Networks',
        'Services': 'dmd.Services'
    }

    if cli_options['list'] or not cli_options['type']:
        # Output list of present catalogs to the UI, perform no further operations
        print "List of dmd types that support reIndex() calls from this script:\n"
        print "\n".join(types_to_reIndex.keys())
        log.info(
            "Zenreindextool finished - list of supported types output to CLI")
    else:
        if cli_options['type'] in types_to_reIndex.keys():
            any_issue = reindex_dmd_objects(
                cli_options['type'], types_to_reIndex[cli_options['type']],
                dmd, log)
            # exit with error if there are any issues
            if any_issue == False:
                exit(1)
        else:
            print("Type '%s' unrecognized - unable to reIndex()" %
                  (cli_options['type']))
            log.error("CLI input '%s' doesn't match recognized types" %
                      (cli_options['type']))
            exit(1)

    # Print final status summary, update log file with termination block
    print("\n[%s] Execution finished in %s\n" %
          (time.strftime("%Y-%m-%d %H:%M:%S"),
           datetime.timedelta(seconds=int(time.time() - execution_start))))
    log.info("zenindextool completed in %1.2f seconds" %
             (time.time() - execution_start))
    log.info("############################################################")
Exemple #7
0
def main():
    """ Scans through zodb hierarchy (from user-supplied path, defaults to /,  checking for PKEs """

    execution_start = time.time()
    cli_options = parse_options()
    log = configure_logging('findposkeyerror')
    log.info("Command line options: %s" % (cli_options))
    if cli_options['debug']:
        log.setLevel(logging.DEBUG)

    # Attempt to get the zenoss.toolbox lock before any actions performed
    if not 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': Counter(0),
        'error_count': Counter(0),
        'repair_count': 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):\n" % (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)
        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 ((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)
Exemple #8
0
def eventStats():
    try:
        import Globals
        from Products.ZenUtils.ZenScriptBase import ZenScriptBase
        from Products.Zuul import getFacade
        zsb = ZenScriptBase(noopts=True, connect=True)
        zsb.getDataRoot()
        zepfacade = getFacade('zep')
        statsList = zepfacade.getStats()
        return '\n\n'.join([str(item) for item in statsList])
    except Exception, ex:
        log = logging.getLogger('zendiag')
        log.exception(ex)
    def validate(self, argz):
        dmd = ZenScriptBase(noopts=True, connect=True).dmd
        impactPack = dmd.ZenPackManager.packs.findObjectsById(
            'ZenPacks.zenoss.Impact')
        if not impactPack:
            log.info('The Impact ZenPack is not installed')
            return

        impactPack = impactPack[0]
        if cmp(parse_version(impactPack.version),
               parse_version(MIN_ZP_VERS)) > 0:
            log.info('Impact ZenPack version %s is installed, OK to migrate',
                     impactPack.version)
            return

        log.error('ZenPacks.zenoss.Impact is at version %s, but must be ' \
                  'at least version %s, exiting', impactPack.version, MIN_ZP_VERS)
        raise ValidationException()
def main():
    parser = argparse.ArgumentParser(description="Find POSKeyErrors 1.4")
    parser.add_argument(
        "folder",
        metavar="PATH",
        type=str,
        help="Object path where to start searching from.  E.g. Devices.Server")
    parser.add_argument("--fixrels",
                        action="store_true",
                        default=False,
                        help="Automatically fix ZenRelationship objects")
    args = parser.parse_args()
    #import pdb; pdb.set_trace()

    # Configure NullHandler for logging to suppress 'no handler for
    # logger' messages.
    logger = logging.getLogger()
    logger.addHandler(logging.NullHandler())

    ZenScriptBase.doesLogging = False  # disable logging configuration
    dmd = ZenScriptBase(noopts=True, connect=True).dmd
    # Split along '/' and '.' delimiters
    path = re.split("[./]", args.folder)
    # If the first path element is 'app' (name of root node in zendmd),
    # then remove it from the path, because that name doesn't actually
    # exist in the database.
    if path[0] == "app":
        path = path[1:]
    # Rebuild path using '/' delimiter
    path = '/'.join(path) if path else '/'
    try:
        folder = dmd.getObjByPath(path)
    except KeyError:
        print "Invalid path: %s" % (args.folder, )
    else:
        for exname, ex, objType, objId, parentPath in findPOSKeyErrors(folder):
            print "%s: %s on %s '%s' of %s" \
                % (exname, ex, objType, objId, _getPathStr(parentPath))
            # example == POSKeyError: 0x0118ef28 on relationship 'dependents' of app.zport.dmd.Devices.VMware.TNL1DMZVC01.Hosts.devices.TNL1DMZVC01_host-125.hw
            if args.fixrels:
                if isinstance(ex, POSKeyError):
                    fixPOSKeyError(exname, ex, objType, objId, parentPath)
def main():
    '''Scans zodb objects for ZenRelations issues.  If --fix, attempts repair.'''

    execution_start = time.time()
    cli_options = parse_options()
    log = configure_logging('zenrelationscan')
    log.info("Command line options: %s" % (cli_options))
    if cli_options['debug']:
        log.setLevel(logging.DEBUG)

    counters = {
        'item_count': Counter(0),
        'error_count': Counter(0),
        'repair_count': Counter(0)
    }

    # Attempt to get the zenoss.toolbox lock before any actions performed
    if not get_lock("zenoss.toolbox", log):
        sys.exit(1)

    # Obtain dmd ZenScriptBase connection
    dmd = ZenScriptBase(noopts=True, connect=True).dmd
    log.debug("ZenScriptBase connection obtained")

    scan_relationships(cli_options['fix'], cli_options['cycles'],
                       cli_options['unlimitedram'], dmd, log, counters)

    # Print final status summary, update log file with termination block
    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)
Exemple #12
0
def get_device_properties():
    """Retrieve device attributes from Zenoss and store in local data structure (slots).
"""     
    dmd = ZenScriptBase(connect=True).dmd
    
    #Retrieve device attributes from Zenoss and store in local data structure (slots).
    print("get_device_properties")     

    global slots
    global groupName
     
    for device in dmd.Devices.getSubDevices():
        groups = device.getDeviceGroupNames()
        
        for a in range (0,len(groups)):
            if groups[a].find(groupName) != -1:
		# NOTE: ZNYX BOARDS DON'T HAVE CORRECT SLOT NUMBER
                #slot = device.rackSlot
                #slotWords = (str(slot)).split()
                #slotNum = int(slotWords[len(slotWords)-1]) 
                serialNum = device.getHWSerialNumber()
                if serialNum == None:
		    serialNum = ""		
		ip = device.getManageIp()
                name = device.getDeviceName()                
                classPath = device.getDeviceClassPath()
                classPath.strip()
                classes = classPath.split('/')
                className = classes[len(classes)-1]
                
                # Find the right slot.
                for slotNum in range (0,len(slots)):
		     if slots[slotNum]['ip'] == ip:
                        # Store info in slots
                        slotInfo = slots[slotNum]
                        slotInfo['zname'] = name 
                        slotInfo['class'] = className
                        slotInfo['serial'] = serialNum
                        break
Exemple #13
0
def main():
    scriptSummary = "Export event from redis or send exported to Zenoss"
    scriptName = os.path.basename(__file__).split('.')[0]
    scriptVersion = '1.0.0'

    parser = ZenToolboxUtils.parse_options(
        scriptVersion, "%s: %s" % (scriptName, scriptSummary))
    parser.add_argument('-e',
                        '--export',
                        action='store',
                        metavar='FILENAME',
                        help='Export events from redis')
    parser.add_argument('-p',
                        '--pretty',
                        action='store_true',
                        default=False,
                        help='Export events in a pretty format')
    parser.add_argument('-l',
                        '--load',
                        action='store',
                        metavar='FILENAME',
                        help='Send events from file into Zenoss')

    cli_options = vars(parser.parse_args())

    dmd = ZenScriptBase(noopts=True, connect=True).dmd

    r = redis.StrictRedis(
        dmd.getProperty('eventReplayRedisServer'),
        dmd.getProperty('eventReplayRedisPort'),
        db=dmd.getProperty('eventReplayRedisDB'),
    )

    if cli_options['export']:
        exportEvents(r, cli_options['export'], cli_options['pretty'])
        sys.exit()
    elif cli_options['load'] and os.path.isfile(cli_options['load']):
        importEvents(dmd, cli_options['load'])
Exemple #14
0
    def processResults(self, cmd, result):
        """
    Process the results for command "lsdrive -delim :".
    """
        update = False
        datapointMap = dict([(dp.id, dp) for dp in cmd.points])
        devname = cmd.deviceConfig.device

        # returned from datasource component field with ${here/id}
        componentid = cmd.component

        rresult = Utils.cmdParser(cmd.result.output, 'id', 'DRIVE_ID')
        # specific component device
        rresult = rresult[componentid]

        # drive status raise event
        if rresult['status'] != 'online':
            result.events.append(
                Utils.getEvent(cmd, "Drive status not online", clear=False))
            update = True

        # drive error sequence number
        if rresult['error_sequence_number'] != '':
            result.events.append(
                Utils.getEvent(cmd,
                               "Drive error sequence number: " +
                               rresult['error_sequence_number'],
                               clear=False))
            update = True

        # update current component if needed
        if update:
            scriptbase = ZenScriptBase(noopts=1, connect=True)
            device = scriptbase.findDevice(devname)
            component = device.drives.findObjectsById(componentid)[0]
            component.drive_status = rresult['status']
            component.error_sequence_number = rresult['error_sequence_number']
            commit()
    def __init__(self,
                 error_queue,
                 idx,
                 worker_count,
                 parent_queue,
                 counter,
                 semaphore,
                 cond,
                 cancel,
                 terminator,
                 fields=None,
                 logtoggle=None):
        super(ReindexProcess, self).__init__()

        self.error_queue = error_queue
        self.idx = idx
        self.worker_count = worker_count
        self.parent_queue = parent_queue
        self.counter = counter

        self.semaphore = semaphore
        self.cond = cond
        self.cancel = cancel
        self.terminator = terminator
        self.fields = fields
        self.logtoggle = logtoggle

        self.semaphore_acquired = False

        self._batch = []

        zsb = ZenScriptBase(connect=True, should_log=False)
        self.dmd = zsb.dmd
        self._db = zsb.db
        self.index_client = zope.component.createObject(
            'ModelIndex', get_solr_config())
def main():
    """Scans catalogs for broken references.  If --fix, attempts to remove broken references."""

    executionStart = 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="12",
                        type=int,
                        help="maximum times to cycle (with --fix, <= 12)")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        default=False,
                        help="output all supported catalogs")
    parser.add_argument("-c",
                        "--catalog",
                        action="store",
                        default="",
                        help="only scan/fix specified catalog")
    cliOptions = vars(parser.parse_args())
    log, logFileName = ZenToolboxUtils.configure_logging(
        scriptName, scriptVersion, cliOptions['tmpdir'])
    log.info("Command line options: %s" % (cliOptions))
    if cliOptions['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")

    anyIssue = False
    global maxCycles
    if cliOptions['fix']:
        if cliOptions['cycles'] > 12:
            maxCycles = 12
        else:
            maxCycles = cliOptions['cycles']
    else:
        maxCycles = 1

    validCatalogList = build_catalog_list(dmd, log)
    if cliOptions['list']:
        print "List of supported Zenoss catalogs to examine:\n"
        for item in validCatalogList:
            print item.prettyName
        log.info(
            "Zencatalogscan finished - list of supported catalogs output to CLI"
        )
    else:
        if cliOptions['catalog']:
            foundItem = False
            for item in validCatalogList:
                if cliOptions['catalog'] == item.prettyName:
                    foundItem = True
                    anyIssue = scan_catalog(item, cliOptions['fix'], dmd, log,
                                            not cliOptions['skipEvents'])
            if not foundItem:
                print("Catalog '%s' unrecognized - unable to scan" %
                      (cliOptions['catalog']))
                log.error("CLI input '%s' doesn't match recognized catalogs" %
                          (cliOptions['catalog']))
                exit(1)
        else:
            for item in validCatalogList:
                anyIssue = scan_catalog(
                    item, cliOptions['fix'], dmd, log,
                    not cliOptions['skipEvents']) or anyIssue

    # Print final status summary, update log file with termination block
    print("\n[%s] Execution finished in %s\n" %
          (time.strftime("%Y-%m-%d %H:%M:%S"),
           datetime.timedelta(seconds=int(time.time() - executionStart))))
    log.info("zencatalogscan completed in %1.2f seconds" %
             (time.time() - executionStart))
    log.info("############################################################")

    if not cliOptions['skipEvents']:
        if anyIssue:
            eventSummaryMsg = "%s encountered errors (took %1.2f seconds)" % (
                scriptName, (time.time() - executionStart))
            eventSeverity = 4
        else:
            eventSummaryMsg = "%s completed without errors (took %1.2f seconds)" % (
                scriptName, (time.time() - executionStart))
            eventSeverity = 2

        ZenToolboxUtils.send_summary_event(eventSummaryMsg, eventSeverity,
                                           scriptName, "executionStatus",
                                           documentationURL, dmd)

    if anyIssue and not cliOptions['fix']:
        print("** WARNING ** Issues were detected - Consult KB article at")
        print("      https://support.zenoss.com/hc/en-us/articles/203118075\n")
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #17
0
def main():
    '''Checks for old/unused ip addresses.  If --fix, attempts to remove old unused ip addresses.
       Builds list of available non-empty catalogs.'''

    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 stale references")
    parser.add_argument("-n",
                        "--cycles",
                        action="store",
                        default="12",
                        type=int,
                        help="maximum times to cycle (with --fix)")
    parser.add_argument("-l",
                        "--list",
                        action="store_true",
                        default=False,
                        help="output all supported catalogs")
    parser.add_argument("-c",
                        "--catalog",
                        action="store",
                        default="",
                        help="only scan/fix specified catalog")
    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")

    any_issue = [False, 0]
    unrecognized_catalog = False

    # Build list of catalogs, then process catalog(s) and perform reindex if --fix
    present_catalog_dict = build_catalog_dict(dmd, log)
    if cli_options['list']:
        # Output list of present catalogs to the UI, perform no further operations
        print "List of supported Zenoss catalogs to examine:\n"
        print "\n".join(present_catalog_dict.keys())
        log.info(
            "zennetworkclean finished - list of supported catalogs output to CLI"
        )
    else:
        # Scan through catalog(s) depending on --catalog parameter
        if cli_options['catalog']:
            if cli_options['catalog'] in present_catalog_dict.keys():
                # Catalog provided as parameter is present - scan just that catalog
                any_issue = scan_catalog(
                    cli_options['catalog'],
                    present_catalog_dict[cli_options['catalog']],
                    cli_options['fix'], cli_options['cycles'], dmd, log)
            else:
                unrecognized_catalog = True
                print("Catalog '%s' unrecognized - unable to scan" %
                      (cli_options['catalog']))
                log.error("CLI input '%s' doesn't match recognized catalogs" %
                          (cli_options['catalog']))
        else:
            # Else scan for all catalogs in present_catalog_dict
            for catalog in present_catalog_dict.keys():
                any_issue = scan_catalog(
                    catalog, present_catalog_dict[catalog], cli_options['fix'],
                    cli_options['cycles'], dmd, log) or any_issue

    # Print final status summary, update log file with termination block
    print("\n[%s] Execution finished in %s\n" %
          (time.strftime("%Y-%m-%d %H:%M:%S"),
           datetime.timedelta(seconds=int(time.time() - execution_start))))
    log.info("zennetworkclean completed in %1.2f seconds" %
             (time.time() - execution_start))
    log.info("############################################################")

    if any_issue and not cli_options['fix']:
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #18
0
def main():
    '''Performs reindex call on different DMD categories (used to be a part of zencatalogscan)'''

    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("-l",
                        "--list",
                        action="store_true",
                        default=False,
                        help="output all supported reIndex() types")
    parser.add_argument("-t",
                        "--type",
                        action="store",
                        default="",
                        help="specify which type to reIndex()")
    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")

    any_issue = False

    # Else build list of catalogs, then process catalog(s) and perform reindex if --fix
    types_to_reIndex = {
        'Devices': 'dmd.Devices',
        'Events': 'dmd.Events',
        'Manufacturers': 'dmd.Manufacturers',
        'Networks': 'dmd.Networks',
        'Services': 'dmd.Services',
    }

    if not USE_MODEL_CATALOG:
        types_to_reIndex['DeviceSearch'] = ' dmd.Devices.deviceSearch'

    if cli_options['list'] or not cli_options['type']:
        # Output list of present catalogs to the UI, perform no further operations
        print "List of dmd types that support reIndex() calls from this script:\n"
        print "\n".join(types_to_reIndex.keys())
        log.info(
            "Zenreindextool finished - list of supported types output to CLI")
        exit(1)

    if cli_options['type'] in types_to_reIndex.keys():
        any_issue = reindex_dmd_objects(cli_options['type'],
                                        types_to_reIndex[cli_options['type']],
                                        dmd, log)
    else:
        print("Type '%s' unrecognized - unable to reIndex()" %
              (cli_options['type']))
        log.error("CLI input '%s' doesn't match recognized types" %
                  (cli_options['type']))
        exit(1)

    # Print final status summary, update log file with termination block
    print("\n[%s] Execution finished in %s\n" %
          (time.strftime("%Y-%m-%d %H:%M:%S"),
           datetime.timedelta(seconds=int(time.time() - execution_start))))
    log.info("zenindextool completed in %1.2f seconds" %
             (time.time() - execution_start))
    log.info("############################################################")

    if any_issue:
        print("** WARNING ** Issues were encountered - Consult KB article at")
        print("      https://support.zenoss.com/hc/en-us/articles/203263689\n")
        sys.exit(1)

    sys.exit(0)
Exemple #19
0
def zenossInfo():
    "get the About:Versions page data"

    def format_data(fmt, data):
        return [fmt % datum for datum in data] + ['']

    try:
        print "Gathering info from zodb..."
        import Globals
        from Products.ZenUtils.ZenScriptBase import ZenScriptBase
        from Products.Zuul import getFacade
        zsb = ZenScriptBase(noopts=True, connect=True)
        zsb.getDataRoot()

        header_data = [('Report Data', datetime.datetime.now()),
                       ('Server Key', zsb.dmd.uuid),
                       ('Google Key', zsb.dmd.geomapapikey)]

        counter = {}
        decomm = 0
        for d in zsb.dmd.Devices.getSubDevices():
            if d.productionState < 0:
                decomm += 1
            else:
                index = '%s %s' % \
                    (d.getDeviceClassPath(), d.getProductionStateString())
                count = counter.get(index, 0)
                counter[index] = count + 1

        totaldev = zsb.dmd.Devices.countDevices()

        device_summary_header_data = [
            ('Total Devices', totaldev),
            ('Total Decommissioned Devices', decomm),
            ('Total Monitored Devices', totaldev - decomm),
        ]

        device_summary_header = ['Device Breakdown by Class and State:']

        counter_keylist = counter.keys()
        counter_keylist.sort()
        device_summary_data = [(k, counter[k]) for k in counter_keylist]

        zenpacks_header = ['ZenPacks:']
        zenpack_ids = zsb.dmd.ZenPackManager.packs.objectIds()

        zenoss_versions_data = [(record['header'], record['data'])
                                for record in zsb.dmd.About.getAllVersions()]

        uuid_data = [('uuid', zsb.dmd.uuid)]

        event_start = time.time() - 24 * 60 * 60

        product_count = 0
        for name in zsb.dmd.Manufacturers.getManufacturerNames():
            for product_name in zsb.dmd.Manufacturers.getProductNames(name):
                product_count = product_count + 1

        # Hub collector Data
        collector_header = ['Hub and Collector Information']
        hub_data = []
        remote_count = 0
        local_count = 0
        for hub in zsb.dmd.Monitors.Hub.getHubs():
            hub_data.append("Hub: %s" % hub.id)
            for collector in hub.collectors():
                hub_data.append("\tCollector: %s IsLocal(): %s" %
                                (collector.id, collector.isLocalHost()))
                if not collector.isLocalHost():
                    hub_data.append("\tCollector(Remote): %s" % collector.id)
                    remote_count = remote_count + 1
                else:
                    hub_data.append("\tCollector(Local): %s " % collector.id)
                    local_count = local_count + 1

        zep = getFacade('zep')
        tail_data = [
            ('Evt Rules', zsb.dmd.Events.countInstances()),
            ('Evt Count (Last 24 Hours)', zep.countEventsSince(event_start)),
            ('Reports', zsb.dmd.Reports.countReports()),
            ('Templates', zsb.dmd.Devices.rrdTemplates.countObjects()),
            ('Systems', zsb.dmd.Systems.countChildren()),
            ('Groups', zsb.dmd.Groups.countChildren()),
            ('Locations', zsb.dmd.Locations.countChildren()),
            ('Users', len(zsb.dmd.ZenUsers.getUsers())),
            ('Product Count', product_count),
            ('Local Collector Count', local_count),
            ('Remote Collector Count', remote_count)
        ]

        detail_prefix = '    '
        std_key_data_fmt = '%s: %s'
        detail_std_key_data_fmt = detail_prefix + std_key_data_fmt
        detail_data_fmt = detail_prefix + '%s'
        center_justify_fmt = '%10s: %s'

        return_data = (
            format_data(std_key_data_fmt, header_data) +
            format_data(std_key_data_fmt, device_summary_header_data) +
            device_summary_header +
            format_data(detail_std_key_data_fmt, device_summary_data) +
            zenpacks_header + format_data(detail_data_fmt, zenpack_ids) +
            format_data(center_justify_fmt, zenoss_versions_data + uuid_data) +
            collector_header + format_data('%s', hub_data) +
            format_data(std_key_data_fmt, tail_data))

        return '\n'.join(return_data)

    except Exception, ex:
        log.exception(ex)
 def _get_zodb_connection(self):
     print("Connecting to zodb...")
     from Products.ZenUtils.ZenScriptBase import ZenScriptBase
     self.dmd = ZenScriptBase(connect=True).dmd
Exemple #21
0
p.set_defaults(cust_name="Enterprise Customer")
#  Title  - example "Internal IT Infrastructure"
p.add_option("-t", "--title", action="store", dest="title_text")
p.set_defaults(title_text="Architecture Review")
opts, args = p.parse_args()
outfile = opts.outfile
cust_name = opts.cust_name
title_text = opts.title_text
args = None
# Open file to write results
out = open(outfile + ".txt", "w")
jsonout = open(outfile + ".json", "w")

# Connect to DMD
print "Trying to connect to DMD"
zenscript = ZenScriptBase(connect=True, noopts=1)
dmd = None
try:
    dmd = zenscript.dmd
    print "Connected to DMD.  Zenoss version found: %s" % dmd.version
except Exception, e:
    print "Connection to zenoss dmd failed: %s\n" % e
    sys.exit(1)


def _discoverLocalhostNames():
    names = set()
    # check the many variants of hostname
    for args in ("", "-i", "-I", "-a", "-A", "-s"):
        cmd = "hostname %s" % args
        p = subprocess.Popen(cmd,
Exemple #22
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)
Exemple #23
0
def process_config_changes(slots):
    """Determine if chassis or Zenoss configuration has changed and process any changes.
"""

    # CHASSIS CHANGES
    newSlots = [None] * maxSlots
    slotStatus = [None] * maxSlots

    # Initialize IP addresses in new table.
    for slotNum in range(0, len(slots)):
        newSlots[slotNum] = {'ip': slots[slotNum]['ip']}

    # Derive the device class from the device itself. Then get the latest serial number and
    # mState from the shelf manager.
    # NOTE: Order is important. Call setup_chassis before get_device_names.

    setup_chassis(newSlots)
    get_device_names(newSlots, False)

    for slotNum in range(1, len(newSlots)):

        newSlotInfo = newSlots[slotNum]
        slotInfo = slots[slotNum]

        # Error condition. Neither of these will be empty.
        if newSlotInfo == None or slotInfo == None:
            # NOTE: Generate event
            continue

# Retrieve serial number and mState.
        newSerial = newSlotInfo['serial']
        newMState = int(newSlotInfo['mState'])
        newClass = newSlotInfo['class']

        oldSerial = slotInfo['serial']
        oldMState = int(slotInfo['mState'])
        oldClass = slotInfo['class']

        if newMState == 0:
            if oldMState == 0 or oldClass == None or oldSerial == None:
                # No Change -- slot still empty.
                slotStatus[slotNum] = boardUnchanged
            else:
                # Board Removed.
                slotStatus[slotNum] = boardRemoved
        else:
            if ((oldMState == 0) or (oldClass == None) or (oldSerial == None)):
                # Board Added
                slotStatus[slotNum] = boardAdded
            elif (newSerial != oldSerial) or (newClass != oldClass):
                # Hot Swap
                slotStatus[slotNum] = boardHotSwap
            else:
                # No Change
                slotStatus[slotNum] = boardUnchanged

    # ZENOSS CHANGES

    # Setup dmd object
    dmd = ZenScriptBase(connect=True).dmd

    for device in dmd.Devices.getSubDevices():
        groups = device.getDeviceGroupNames()
        for a in range(0, len(groups)):
            if groups[a].find(groupName) != -1:
                slot = device.rackSlot
                slotWords = (str(slot)).split()
                slotNum = int(slotWords[len(slotWords) - 1])

                serialNum = device.getHWSerialNumber()
                name = device.getDeviceName()
                ip = device.getManageIp()
                classPath = device.getDeviceClassPath()
                classPath.strip()
                classes = classPath.split('/')
                className = classes[len(classes) - 1]

                # User could have changed slot, serial, ip, name or class.
                # Zenoss modeling will reset slot & serial, so don't worry about these.

                # User not allowed to change IP address in first release. Log error.
                # NOTE: Log error here & generate event. Test changing IP later.

                # User not allowed to change class.
                # NOTE: Log error here & generate event.

                # User can change name...This is OK. Just update internal tables.
                newSlots[slotNum]['name'] = name
                slots[slotNum]['name'] = name

    for slotNum in range(1, len(newSlots)):

        status = slotStatus[slotNum]

        if status == None or status == boardUnchanged:
            continue

        if status == boardRemoved:
            device = dmd.Devices.findDevice(
                slots[slotNum]['name'])  # Delete device.
            device.deleteDevice()
            commit()
        else:
            newSlotInfo = newSlots[slotNum]
            newIp = newSlotInfo['ip']
            newName = newSlotInfo['name']
            newClass = newSlotInfo['class']
            newSerial = newSlotInfo['serial']

            if (newClass == "ShelfMgr") or (newClass == "ZXSBC"):
                prefix = "/Network/"
            else:
                prefix = "/Network/OASwitch/"

            newPath = prefix + newClass

            if (status == boardAdded):
                # Add new device via Zenoss.
                add_dmd_device(newIp, newName, newPath, groupName, slotNum,
                               newSerial)
            else:
                # Hot Swap
                # If different class, then delete old device and add new one.
                # Otherwise, generate event.

                if (newClass != slots[slotNum]['class']):
                    device = dmd.Devices.findDevice(slots[slotNum]['name'])
                    device.deleteDevice()
                    commit()
                    add_dmd_device(newIp, newName, newPath, groupName, slotNum,
                                   newSerial)
                else:
                    # NOTE: Add event here.
                    print 'swapped boards of type %s' % newClass

    dmd.Devices.reIndex()
    commit()
Exemple #24
0
def main():
    '''Scans catalogs for broken references.  If --fix, attempts to remove broken references.
       Builds list of available non-empty catalogs.  If --reindex, attempts dmd.reIndex().'''

    execution_start = time.time()
    cli_options = parse_options()
    log = configure_logging('zencatalogscan')
    log.info("Command line options: %s" % (cli_options))
    if cli_options['debug']:
        log.setLevel(logging.DEBUG)

    # Attempt to get the zenoss.toolbox lock before any actions performed
    if not get_lock("zenoss.toolbox", log):
        sys.exit(1)

    # Obtain dmd ZenScriptBase connection
    dmd = ZenScriptBase(noopts=True, connect=True).dmd
    log.debug("ZenScriptBase connection obtained")

    any_issue = False
    unrecognized_catalog = False

    # Build list of catalogs, then process catalog(s) and perform reindex if --fix
    present_catalog_dict = build_catalog_dict(dmd, log)
    if cli_options['list']:
        # Output list of present catalogs to the UI, perform no further operations
        print "List of supported Zenoss catalogs to examine:\n"
        print "\n".join(present_catalog_dict.keys())
        log.info(
            "Zencatalogscan finished - list of supported catalogs output to CLI"
        )
    else:
        # Scan through catalog(s) depending on --catalog parameter
        if cli_options['catalog']:
            if cli_options['catalog'] in present_catalog_dict.keys():
                # Catalog provided as parameter is present - scan just that catalog
                any_issue = scan_catalog(
                    cli_options['catalog'],
                    present_catalog_dict[cli_options['catalog']],
                    cli_options['fix'], cli_options['cycles'], dmd, log)
            else:
                unrecognized_catalog = True
                print("Catalog '%s' unrecognized - unable to scan" %
                      (cli_options['catalog']))
                log.error("CLI input '%s' doesn't match recognized catalogs" %
                          (cli_options['catalog']))
        else:
            # Else scan for all catalogs in present_catalog_dict
            for catalog in present_catalog_dict.keys():
                any_issue = scan_catalog(
                    catalog, present_catalog_dict[catalog], cli_options['fix'],
                    cli_options['cycles'], dmd, log) or any_issue

    # Print final status summary, update log file with termination block
    print("\n[%s] Execution finished in %s\n" %
          (time.strftime("%Y-%m-%d %H:%M:%S"),
           datetime.timedelta(seconds=int(time.time() - execution_start))))
    log.info("zencatalogscan completed in %1.2f seconds" %
             (time.time() - execution_start))
    log.info("############################################################")

    if any_issue and not cli_options['fix']:
        print("** WARNING ** Issues were detected - Consult KB article at")
        print("      https://support.zenoss.com/hc/en-us/articles/203118075\n")
        sys.exit(1)
    else:
        sys.exit(0)
Exemple #25
0
parser = OptionParser()
parser.add_option("-f", "--file", dest="outputFile",
                  help="Please specify full path to output file", metavar="FILE")

(options, args) = parser.parse_args()

if not options.outputFile:
    parser.print_help()
    sys.exit()

of = open(options.outputFile, "w")
localtime = time.asctime( time.localtime(time.time()) )
of.write(localtime + "\n\n")

# Need noopts=True or it barfs with the script options
dmd = ZenScriptBase(connect=True, noopts=True).dmd

deviceList=[]
for dev in dmd.Devices.getSubDevices():
  deviceList.append(dev.id)
#Sort the device on id
deviceList.sort()

for dev in deviceList:
  d = dmd.Devices.findDevice(dev)
  if d.manageIp:
    of.write("Device Id %s \t Device Title %s \t Device manageIp %s \n" % (d.id, d.title, d.manageIp))
  else:
    of.write("Device Id %s \t Device Title %s \t Device manageIp NO IP ADDRESS \n" % (d.id, d.title))

of.close()
Exemple #26
0
    try:
        with open(os.devnull, 'w') as devnull:
            subprocess.check_call(['sudo', 'rabbitmqctl', '-p', vhost, 'clear_permissions', user], stdout=devnull)
            subprocess.check_call(['sudo', 'rabbitmqctl', '-p', vhost, 'set_permissions', user, 'zenoss.openstack.*', 'zenoss.openstack.*', '^$'], stdout=devnull)
    except subprocess.CalledProcessError, e:
        sys.exit("Unable to exceute rabbitmqctl (%s)" % e)


if __name__ == '__main__':
    if not VERSION5:
        require_rabbitmq()
        create_exchanges()

    # Log into ZODB..
    try:
        script = ZenScriptBase()
        script.connect()
        dmd = script.dmd
    except Exception, e:
        sys.exit("Unable to connect to ZODB: %s" % e)

    create_default_credentials(dmd)

    if not VERSION5:
        provision_user(dmd)

    rabbit_ip = {}
    if VERSION5:
        from Products.ZenUtils.controlplane.application import getConnectionSettings
        from Products.ZenUtils.controlplane import ControlPlaneClient
Exemple #27
0
    root = ET.Element(roottag)
    _convert_dict_to_xml_recurse(root, xmldict, listnames)
    return root
    
def dict2xml(datadict, roottag='data', listnames=None, pretty=False):
    """Converts a dictionary to an UTF-8 encoded XML string.
"""
    root = dict2et(datadict, roottag, listnames)
    return to_string(root, pretty=True)

print "*****START*****"
    
# Setup dmd object
# NOTE: Do I need this in daemon?

dmd = ZenScriptBase(connect=True).dmd

# Initialize lists

slots=[None]*maxSlots

# Use zxconfig.xml to set up slot/IP Addr map.     
try:
     configFile = open(zxconfigFileName)
except IOError:
     # NOTE: Send event & log error & QUIT
     print "Unable to find zxconfig.xml"
     # Quit. zxconfig.xml must be present for initialization.
     sys.exit()
	 
configDoc = parse(configFile)
Exemple #28
0
def get_zodb_connection():
    print("Connecting to zodb...")
    from Products.ZenUtils.ZenScriptBase import ZenScriptBase
    return ZenScriptBase(connect=True).dmd
Exemple #29
0
def process_config_changes():
    """Determine if chassis or Zenoss configuration has changed and process any changes.
""" 
    #Determine if chassis or Zenoss configuration has changed and process any changes.
    print("process_config_changes")  
    
    global slots
    global groupName
    
    global boardRemoved
    global boardAdded
    global boardHotSwap
    global boardUnchanged  
    global boardUnhealthy
    
    global noneMState
    global actReqMState
    global actMState
    global fruActiveMState
    
    global shelfMgrClass
    global zxsbcClass
    global znyxPrefix
    global nonZnyxPrefix

    # Get dmd
    dmd = ZenScriptBase(connect=True).dmd
    
    # CHASSIS CHANGES
    newSlots=[None]*maxSlots
    slotStatus=[None]*maxSlots 
     
    # Initialize IP addresses in new table.
    for slotNum in range (0,len(slots)):
        newSlots[slotNum] = {'ip': slots[slotNum]['ip']}
        
    # Derive the device class from the device itself. Then get the latest serial number and 
    # mstate from the shelf manager.
    # NOTE: Order is important. Call setup_chassis before get_device_name.

    setup_chassis(newSlots)

    # If unable to contact shelf manager then return.
    if newSlots[0]['status'] == "unreachable":
	print ("process_config_changes: can't contact shelf manager")
        return
   
    get_device_classes(newSlots)
    
    for slotNum in range (1,len(newSlots)): 
        newSlotInfo = newSlots[slotNum]
        slotInfo = slots[slotNum]
        
        # Error condition. Neither of these will be empty.      
        if newSlotInfo == None or slotInfo == None:
	    # Generate event
	    print "zxchassisdaemon: Empty slot info (internal data)"
	    continue	

	# If can't get new slot info then continue.
	if newSlotInfo['status'] == "unreachable":
	    continue
	    
        # Retrieve serial number and mstate.
        newSerial = newSlotInfo['serial']
        newMState = int(newSlotInfo['mstate'])
        newClass = newSlotInfo['class']

        oldSerial = slotInfo['serial']
        oldMState = int(slotInfo['mstate'])
        oldClass = slotInfo['class']
 
        if newMState == noneMState:
            if oldMState == noneMState or oldClass == None or oldSerial == None:               
		# No Change -- slot still empty.
		slotStatus[slotNum] = boardUnchanged 		  
	    else:	
		# Board Removed.
		slotStatus[slotNum] = boardRemoved 
        elif newMState == fruActiveMState or newMState == actReqMState or newMState == actMState:
	    if ((oldMState == noneMState) or (oldClass == None) or (oldSerial == None)):
		# Board Added
		slotStatus[slotNum] = boardAdded             
		print("BOARD ADDED: newSerial = %s, newMState= %s, newClass= %s" % (newSerial, newMState, newClass))
		print("oldSerial = %s, oldMState= %s, oldClass= %s" % (oldSerial, oldMState, oldClass))
	    elif (newSerial != oldSerial) or (newClass != oldClass):		
		# Hot Swap
		slotStatus[slotNum] = boardHotSwap 
		print("BOARD HOTSWAP: newSerial = %s, newMState= %s, newClass= %s" % (newSerial, newMState, newClass))
		print("oldSerial = %s, oldMState= %s, oldClass= %s" % (oldSerial, oldMState, oldClass))
            else:		
		# No Change
		slotStatus[slotNum] = boardUnchanged
	else:
	    # Board is inactive, deactivating, or not communicating.
	    # Delete device if it exists.
	    slotStatus[slotNum] = boardUnhealthy
 		       
    # ZENOSS CHANGES

    foundDevices=[False]*maxSlots  
        
    for device in dmd.Devices.getSubDevices():  
        groups = device.getDeviceGroupNames()
        for a in range (0,len(groups)):
            if groups[a].find(groupName) != -1:
                slot = device.rackSlot
                slotWords = (str(slot)).split()
                zenossSlotNum = int(slotWords[len(slotWords)-1])                  
                
                serialNum = device.getHWSerialNumber()
                name = device.getDeviceName()
                ip = device.getManageIp()
                classPath = device.getDeviceClassPath()
                classPath.strip()
                classes = classPath.split('/')
                className = classes[len(classes)-1]
                 
                    
                # User could have changed slot, serial, ip, name or class.
                # Zenoss modeling will reset slot & serial, so don't worry about these.
                # NOTE: Znyx will reset slot & serial in private MIB. This slot number
                # is not guaranteed to correspond to chassis slot.

		# Try to find slot by finding a match for the IP address.
		# If there's no match, then delete the device.
		# Changing the IP address is not allowed.
		for slotNum in range (0,len(slots)): 
		    if ip == slots[slotNum]['ip']:
			 break
			     
		if slotNum >= len(slots):
		    print("process_config_changes: invalid managed IP = %s" % ip)
	            continue
			
		foundDevices[slotNum] = True
		    
                # User not allowed to change IP address in first release. 
                # Change it back & generate event.
                # NOTE: Test changing IP later.

                # User not allowed to change class.
                # Change it back & generate event.
                if className != slots[slotNum]['class'] and className != newSlots[slotNum]['class']:
                    print("process_config_changes: user changed device class to %s" % className)
                    if (newSlots[slotNum]['class'] == shelfMgrClass) or (newSlots[slotNum]['class'] == zxsbcClass):
                        prefix = nonZnyxPrefix
	            else:
		        prefix = znyxPrefix		 
	            newClassPath = prefix + newSlots[slotNum]['class']
	            print("slotNum = %s" % slotNum)
	            print("newClassPath = %s" % newClassPath)
                    device.moveDevices(newClassPath,device.id)
               
                # User can change name...This is OK. Just update internal tables.
                newSlots[slotNum]['zname'] = name
                     
    for slotNum in range (1,len(newSlots)): 
    
        status = slotStatus[slotNum]
                 
        if status == None:
            continue
	   
	if newSlots[slotNum]['status'] == "unreachable":
	    continue
	   
	# Check for case where user might have deleted a valid device in Zenoss.
	# This would be a user error that should be corrected.
	    
	if (status == boardUnchanged):
	    if (newSlots[slotNum]['class'] != None) and (foundDevices[slotNum] == False):
		status = boardAdded
	    else:
		continue
		
        if (status == boardUnhealthy): 
            continue
	   
        if status == boardRemoved: 
            if foundDevices[slotNum] == True:
                device = dmd.Devices.findDevice(slots[slotNum]['ip']) 
                # Delete device.
                if not device:
		    print("cannot find device in slot %s to delete" % slotNum)
		else:     
		    device.deleteDevice()
                    commit()
            learSlot(slotNum)
        else:	     
	    newSlotInfo = newSlots[slotNum]	    
	    newIp = newSlotInfo['ip']
	    #newName = newSlotInfo['zname']
	    newClass = newSlotInfo['class']
	    newSerial = newSlotInfo['serial']

    	    if (newClass == shelfMgrClass) or (newClass == zxsbcClass):
                prefix = nonZnyxPrefix
	    else:
	        prefix = znyxPrefix
		
	    newClassPath = prefix + newClass

	    if (status == boardAdded):
		# Get new name.
		get_device_name(newSlotInfo)
		newName = newSlotInfo['zname']
		    
		# Add new device via Zenoss.
		print("add for boardAdded")
                add_dmd_device(newIp, newName, newClassPath, groupName, slotNum, newSerial)
	    else:
		# Hot Swap
                # If different class, then delete old device and add new one.
                # Otherwise, generate event.
 
                if (newClass != slots[slotNum]['class']):
		    if foundDevices[slotNum] == True:
		        device = dmd.Devices.findDevice(slots[slotNum]['ip'])
		        if not device:
			    print("cannot find device in slot %s to delete" % slotNum)
			else:
		            device.deleteDevice()
		            commit()
		    clearSlot(slotNum)
		        
		    # Get new name.
		    get_device_name(newSlotInfo)
		    newName = newSlotInfo['zname']
		    print("add for hotswap: slotNum=%s, newIP=%s, newClass = %s, slots['class']= %s" % (slotNum, newIp, newClass, slots[slotNum]['class']))
                    # Add new device via Zenoss
		    add_dmd_device(newIp, newName, newClassPath, groupName, slotNum, newSerial)
                else:
		    print ("zxchassisdaemon: Hot swap in slot = %s." % str(slotNum))
                          
            slots[slotNum]['ip'] = newIp 
	    slots[slotNum]['zname'] = newSlotInfo['zname']
	    slots[slotNum]['class'] = newClass
	    slots[slotNum]['serial'] = newSerial

    dmd.Devices.reIndex()
    commit()
def run(processor_count=8,
        hard=False,
        root="",
        indexes=None,
        types=(),
        terminator=None,
        toggle_debug=None):
    if hard and (root or indexes or types):
        raise Exception(
            "Root node, indexes, and types can only be specified during soft re-index"
        )

    log.info("Beginning {0} redindexing with {1} child processes.".format(
        "hard" if hard else "soft", processor_count))

    start = time.time()

    log.info("Initializing model database and Solr model catalog...")
    dmd = ZenScriptBase(connect=True).dmd
    index_client = init_model_catalog()

    processes = []
    error_queue = multiprocessing.Queue()
    parent_queue = multiprocessing.Queue()
    counter = multiprocessing.Value(ctypes.c_uint32)
    semaphore = multiprocessing.Semaphore(processor_count)
    cond = multiprocessing.Condition()

    if not terminator:
        terminator = multiprocessing.Event()

    cancel = multiprocessing.Event()

    processes_remaining = 0
    work = []
    Worker = None

    proc_start = time.time()

    def hard_index_is_done():
        return terminator.is_set() or (semaphore.get_value() == 0
                                       and parent_queue.empty())

    def soft_index_is_done():
        return cancel.is_set() or terminator.is_set()

    # In the case of early termination, we only want to wait up to 30 seconds
    # In the case of straggler processes, we wait up to an hour
    def get_timeout():
        if terminator.is_set():
            return 30
        return 3600

    if hard:
        log.info("Clearing Solr data")
        index_client.clear_data()
        work.append("/zport")
        Worker = HardReindex
        is_done = hard_index_is_done
    else:
        log.info("Reading uids from Solr")
        work = get_uids(index_client, root, types)
        Worker = SoftReindex
        is_done = soft_index_is_done

    log.info("Starting child processes")
    for n in range(processor_count):
        p = Worker(error_queue, n, processor_count, parent_queue, counter,
                   semaphore, cond, cancel, terminator, indexes, toggle_debug)
        processes.append(p)
        p.start()

    for uid in work:
        parent_queue.put(uid)

    if not hard:
        # Put the terminate sentinel at the end of the queue
        parent_queue.put(TERMINATE_SENTINEL)

    log.info("Waiting for processes to finish")

    lastcount = 0
    last = start
    while True:
        with cond:
            # soft_index_is_done is actually appropriate in both cases
            if soft_index_is_done():
                log.info("Terminating condition met. Done!")
                cancel.set()
                # In case we were terminated before we were waiting
                cond.notify_all()
                break
            cond.wait()

            checkLogging(toggle_debug)

            try:
                # Print any errors we've built up
                while not error_queue.empty():
                    try:
                        idx, exc = error_queue.get_nowait()
                    except Queue.Empty:
                        pass  # This shouldn't happen, but just in case there's a race somehow
                    else:
                        log.error(
                            "Indexing process {0} encountered an exception: {1}"
                            .format(idx, exc))
                # Print status
                with counter.get_lock():
                    delta = counter.value - lastcount
                    if delta > MODEL_INDEX_BATCH_SIZE:
                        now = time.time()
                        persec = delta / (now - last)
                        last, lastcount = now, counter.value
                        log.info("Indexed {0} objects ({1}/sec)".format(
                            lastcount, persec))
                # Check to see if we're done
                log.debug("{0} workers still busy".format(
                    semaphore.get_value()))
                log.debug("parent queue is {0}empty".format(
                    "" if parent_queue.empty() else "not "))
                if is_done():
                    # All workers are idle and there's no more work to do, so the end
                    log.info("Terminating condition met. Done!")
                    cancel.set()
                    break
            finally:
                # Pass the ball back to the child that notified
                cond.notify_all()
    log.info("Indexing complete, waiting for workers to clean up")
    for proc in processes:
        log.debug("Joining proc {0}".format(proc.idx))
        proc.join(get_timeout())
        if proc.is_alive():
            log.warn(
                "Worker {} did not exit within timeout, terminating...".format(
                    proc.idx))
            proc.terminate()
    end = time.time()
    log.info("Total time: {0}".format(end - start))
    log.info("Time to initialize: {0}".format(proc_start - start))
    log.info("Time to process and reindex: {0}".format(end - proc_start))
    log.info("Number of objects indexed: {0}".format(counter.value))