Exemplo n.º 1
0
def parseConf(confName):
    """
    Might eventually find a way to make this more generic and just
    use the master parser over in ligmos, but it's fine for now.
    """
    pConf = confparsers.rawParser(confName)
    eConf = confparsers.checkEnabled(pConf)

    expectedSectionNames = ['printerSetup', 'email',
                            'picam',
                            'databaseSetup', 'databaseQuery']

    returnable = {}
    for section in expectedSectionNames:
        # By default we only store the keys specified in the class.
        #   But of course there are exceptions, mainly due to laziness
        #   and deadlines
        backfill = False
        if section == 'printerSetup':
            clstype = classes.threeDimensionalPrinter
        elif section == 'email':
            clstype = j5.classes.emailSNMP
            backfill = True
        elif section == 'picam':
            clstype = picamclass.piCamSettings
        elif section == 'databaseSetup':
            clstype = ligmosclass.baseTarget
            backfill = True
        else:
            clstype = None

        if clstype is not None:
            try:
                actualConfig = confUtils.assignConf(eConf[section], clstype,
                                                    backfill=backfill)
                if section == 'email':
                    # Read in the footer file as a text string
                    try:
                        with open(pConf['email']['footer'], 'r') as f:
                            actualConfig.footer = f.read()
                    except (OSError, IOError):
                        actualConfig.footer = None

                validSect = {section: actualConfig}
            except KeyError:
                print("WARNING: MISSING EXPECTED CONFIGURATION SECTION!")
                print("%s NOT FOUND OR NOT ENABLED IN %s" %
                      (section, confName))
                validSect = {section: None}

        returnable.update(validSect)

    return returnable
Exemplo n.º 2
0
        # Move our files to the set of static filenames. This will
        #   check (cpng) to see if there are actually any files that
        #   are new, and if so it'll shuffle the files into the correct
        #   order of static filenames.
        # This will stamp files that are > 4 hours old with a warning
        utils.copyStaticFilenames(curpngs, lout,
                                  staticname, nstaticfiles,
                                  errorAge=3.5, errorStamp=True)

        print("Sleeping for %03d seconds..." % (sleep))
        time.sleep(sleep)


if __name__ == "__main__":
    outdir = "./outputs/radar/"
    awsconf = "./config/awsCreds.conf"
    forceDownloads = False
    forceRegenPlot = False
    logname = './outputs/logs/radarlove.log'

    # Set up logging (using ligmos' quick 'n easy wrapper)
    logs.setup_logging(logName=logname, nLogs=30)

    # NOTE: We just take a shortcut and use the rawParser here, since we
    #   don't have much in the way of configuration
    creds = confparsers.rawParser(awsconf)

    main(outdir, creds, sleep=90.,
         forceDown=forceDownloads, forceRegen=forceRegenPlot)
    print("Exiting!")
Exemplo n.º 3
0
def main():
    """
    """
    # Define the default files we'll use/look for. These are passed to
    #   the worker constructor (toServeMan).
    devices = '../../conf/mrfreeze.conf'
    deviceconf = classes.instrumentDeviceTarget
    passes = None
    logfile = '../../logs/nora.log'
    desc = "Nora: Heart of the Instrument Cooler Manager"
    eargs = None
    logenable = True

    # Interval between successive runs of the polling loop (seconds)
    bigsleep = 1

    # config: dictionary of parsed config file
    # comm: common block from config file
    # args: parsed options
    # runner: class that contains logic to quit nicely
    config, comm, _, runner = workerSetup.toServeMan(devices,
                                                     passes,
                                                     logfile,
                                                     desc=desc,
                                                     extraargs=eargs,
                                                     conftype=deviceconf,
                                                     enableCheck=False,
                                                     logfile=logenable)

    # Get this PID for diagnostics
    pid = os.getpid()

    # Print the preamble of this particular instance
    #   (helpful to find starts/restarts when scanning thru logs)
    common.printPreamble(pid, config)

    # Reorganize the configuration to be per-instrument so it's a little
    #   easier to loop over and do other stuff with
    allInsts = confparsers.regroupConfig(config,
                                         groupKey='instrument',
                                         ekeys=['devtype', 'extratag'],
                                         delim="+")

    # We need to store our NIHTS compatibility stuff in the above NIHTS
    #   section, to guarantee that it's shared between all devices for that
    #   instrument.  So it needs to be in this level!
    # Also hack in the required password
    print("Looking for NIHTS compatibility section...")
    try:
        compatConfig = confparsers.rawParser("../../conf/compat.conf")
        np = compatConfig['nihts']
        # A cheap hack inside of a cheap hack!
        if np['enabled'].lower() == "false":
            np = None
            print("Warning! Compat info found, but was disabled!")
        else:
            compatClass = compatibility.upfileNIHTS(np)
            allInsts["nihts"].update({"compatibility": compatClass})
            print("NIHTS compatibility layer enabled.")
    except Exception as err:
        print("None found! Skipping.")
        print(str(err))
        np = None

    print("Config:")
    print(allInsts)

    # Check to see if there are any connections/objects to establish
    idbs = connSetup.connIDB(comm)

    # Specify our custom listener that will really do all the work
    #   Since we're hardcoding for the DCTConsumer anyways, I'll take
    #   a bit shortcut and hardcode for the DCT influx database.
    # Someone more clever than I can clean up.
    db = idbs['database-dct']
    amqlistener = listener.MrFreezeConsumer(db=db)

    # TODO: Figure out a way to create a dict of listeners specified
    #   in some creative way. Could add a configuration item to the
    #   file and then loop over it, and change connAMQ accordingly.
    amqtopics = amq.getAllTopics(config, comm, queuerole='master')
    amqs = connSetup.connAMQ(comm, amqtopics, amqlistener=amqlistener)

    # Just hardcode this for now. It's a prototype!
    conn = amqs['broker-dct'][0]
    queue = comm['queue-mrfreeze']

    # Assemble our *initial* schedule of actions. This will be adjusted
    #   by any inputs from the broker once we're in the main loop
    sched = schedule.Scheduler()
    sched = actions.scheduleInstruments(sched,
                                        allInsts,
                                        amqs,
                                        idbs,
                                        debug=True)

    # Before we start the main loop, query all the defined actions
    #   in turn. This will help avoid triggering alerts/warnings/etc.
    # We need to make sure the connection to the broker is up first,
    #   though, because we need to get the LOIS reply topics connected.
    amqs = amq.checkConnections(amqs, subscribe=True)
    sched.run_all(delay_seconds=0.5)

    # Semi-infinite loop
    while runner.halt is False:
        # Check on our connections
        amqs = amq.checkConnections(amqs, subscribe=True)
        # Make sure we update our hardcoded reference
        conn = amqs['broker-dct'][0]

        # Check for any actions, and do them if it's their time
        print("Checking schedule for pending tasks...")
        sched.run_pending()
        for job in sched.jobs:
            remaining = (job.next_run - datetime.now()).total_seconds()
            print("    %s in %f seconds" % (job.tags, remaining))

        # Check for any updates to those actions, or any commanded
        #   actions in general
        print("Cleaning out the queue...")
        queueActions = amqlistener.emptyQueue()
        print("%d items obtained from the queue" % (len(queueActions)))

        # Process and deal with the things in the queue
        allInsts = actions.queueProcessor(sched, queueActions, allInsts, conn,
                                          queue)

        # Diagnostic output
        nleft = len(amqlistener.brokerQueue.items())
        print("%d items still in the queue" % (nleft))
        print("Done for now!")

        # Consider taking a big nap
        if runner.halt is False:
            print("Starting a big sleep")
            # Sleep for bigsleep, but in small chunks to check abort
            for _ in range(bigsleep):
                time.sleep(1)
                if runner.halt is True:
                    break

    # The above loop is exited when someone sends SIGTERM
    print("PID %d is now out of here!" % (pid))

    # Disconnect from all ActiveMQ brokers
    amq.disconnectAll(amqs)

    # The PID file will have already been either deleted/overwritten by
    #   another function/process by this point, so just give back the
    #   console and return STDOUT and STDERR to their system defaults
    sys.stdout = sys.__stdout__
    sys.stderr = sys.__stderr__
    print("STDOUT and STDERR reset.")