Example #1
0
    def test_read_config(self):
        with tempfile.TemporaryDirectory() as tmpdirname:
            tmpfilename = tmpdirname + '/f.yaml'
            create_file(tmpfilename, SAMPLE_JSON.split('\n'))

            result = read_config.read_config(tmpfilename)
            self.assertEqual(result['gyr1']['port'], '/tmp/tty_gyr1')
            self.assertEqual(len(result), 4)

            # Let it figure out that it's JSON
            result = read_config.read_config(tmpfilename)
            self.assertEqual(result['gyr1']['port'], '/tmp/tty_gyr1')
            self.assertEqual(len(result), 4)
Example #2
0
  def __init__(self, config_file, config_name=None, log_level=None):
    """Create a Listener from a Python config file. If the file name
    format is file_name:config, then assume the file_name is that of a
    cruise definition, and look for the config itself under the
    'configs:' key of the file's YAML.
    """
    # If they've got a ':' in the config file name, then we're
    # expecting them to also give us a config name to look for.
    if config_file.find(':') > 0:
      (config_file, config_name) = config_file.split(':', maxsplit=1)
    config = read_config.read_config(config_file)

    if config_name:
      config_dict = config.get('configs', None)
      if not config_dict:
        raise ValueError('Configuration name "%s" specified, but no '
                         '"configs" section found in file "%s"'
                         % (config_name, config_file))
      config = config_dict.get(config_name, None)
      if not config:
        raise ValueError('Configuration name "%s" not found in file "%s"'
                         % (config_name, config_file))

    logging.info('Loaded config file: %s', pprint.pformat(config))
    super().__init__(config=config)
Example #3
0
 def _read_definitions(self, filespec_paths):
     definitions = {}
     for filespec in filespec_paths.split(','):
         logging.debug('reading definitions from %s', filespec)
         for filename in glob.glob(filespec):
             new_defs = read_config.read_config(filename)
             for key in new_defs:
                 if key in definitions:
                     logging.warning('Duplicate definition for key "%s" found in %s',
                                     key, filename)
                 definitions[key] = new_defs[key]
     return definitions
Example #4
0
    def _read_definitions(self, filespec_paths):
        """Read the files on the filespec_paths and return dictionary of
        accumulated definitions.
        """
        definitions = {}
        for filespec in filespec_paths.split(','):
            filenames = glob.glob(filespec)
            if not filenames:
                logging.warning('No files match definition file spec "%s"', filespec)

            for filename in filenames:
                file_definitions = read_config.read_config(filename)

                for new_def_name, new_def in file_definitions.items():
                    if new_def_name in definitions:
                        logging.warning('Duplicate definition for "%s" found in %s',
                                        new_def_name, filename)
                    definitions[new_def_name] = new_def
        return definitions
Example #5
0
def config_from_filename(filename):
    """Load a logger configuration from a filename. If there's a ':' in
    the config file name, then we expect what is before the colon to be
    a cruise definition, and what is after to be the name of a
    configuration inside that definition.
    """
    config_name = None
    if filename.find(':') > 0:
        (filename, config_name) = filename.split(':', maxsplit=1)
    config = read_config(filename)

    if config_name:
        config_dict = config.get('configs', None)
        if not config_dict:
            raise ValueError('Configuration name "%s" specified, but no '
                             '"configs" section found in file "%s"' %
                             (config_name, filename))
        config = config_dict.get(config_name, None)
        if not config:
            raise ValueError('Configuration name "%s" not found in file "%s"' %
                             (config_name, filename))
    logging.info('Loaded config file: %s', pprint.pformat(config))
    return config
Example #6
0
                        dest='mode',
                        required=True,
                        help='Cruise mode to select')

    args = parser.parse_args()

    # Set up logging first of all

    LOG_LEVELS = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG}
    log_level = LOG_LEVELS[min(args.verbosity, max(LOG_LEVELS))]
    logging.basicConfig(format=DEFAULT_LOGGING_FORMAT, level=log_level)

    # What level do we want our component loggers to write?
    logger_log_level = LOG_LEVELS[min(args.logger_verbosity, max(LOG_LEVELS))]

    config = read_config(args.config)

    mode_config_names = config.get('modes').get(args.mode)
    all_configs = config.get('configs')
    mode_configs = {
        logger: all_configs.get(mode_config_names[logger])
        for logger in mode_config_names
    }
    sup = LoggerSupervisor(configs=mode_configs,
                           stderr_file_pattern=args.stderr_file_pattern,
                           stderr_data_server=args.stderr_data_server,
                           max_tries=args.max_tries,
                           min_uptime=args.min_uptime,
                           interval=args.interval,
                           logger_log_level=logger_log_level)
    sup.run()
Example #7
0
                        dest='verbosity',
                        default=0,
                        action='count',
                        help='Increase output verbosity')
    args = parser.parse_args()

    LOGGING_FORMAT = '%(asctime)-15s %(message)s'
    logging.basicConfig(format=LOGGING_FORMAT)

    LOG_LEVELS = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG}
    args.verbosity = min(args.verbosity, max(LOG_LEVELS))
    logging.getLogger().setLevel(LOG_LEVELS[args.verbosity])

    # Okay - get to work here
    if args.config:
        configs = read_config(args.config)
        logging.info('Read configs: %s', configs)
        thread_list = []
        writer_list = []
        for instrument, config in configs.items():
            port = config['port']
            filebase = config['filebase']
            writer = SimNetwork(port=port,
                                filebase=filebase,
                                instrument=instrument)
            writer_thread = threading.Thread(target=writer.run,
                                             kwargs={'loop': args.loop},
                                             daemon=True)
            writer_thread.start()
            thread_list.append(writer_thread)
            writer_list.append('%s %d, %s' % (instrument, port, filebase))
Example #8
0
    def _new_read_definitions(self, filespec_paths, definitions=None):
        """Read the files on the filespec_paths and return dictionary of
        accumulated definitions.

        filespec_paths - a list of possibly-globbed filespecs to be read

        definitions - optional dict of pre-existing definitions that will
                      be added to. Typically this will be omitted on a base call,
                      but may be added to when recursing. Passing it in allows
                      flagging when items are defined more than once.
        """
        # If nothing was passed in, start with base case.
        definitions = definitions or {'devices': {}, 'device_types': {}}

        for filespec in filespec_paths.split(','):
            filenames = glob.glob(filespec)
            if not filenames:
                logging.warning('No files match definition file spec "%s"',
                                filespec)

            for filename in filenames:
                file_definitions = read_config.read_config(filename)

                for key, val in file_definitions.items():
                    # If we have a dict of device definitions, copy them into the
                    # 'devices' key of our definitions.
                    if key == 'devices':
                        if not isinstance(val, dict):
                            logging.error(
                                '"devices" values in file %s must be dict. '
                                'Found type "%s"', filename, type(val))
                            return None

                        for device_name, device_def in val.items():
                            if device_name in definitions['devices']:
                                logging.warning(
                                    'Duplicate definition for "%s" found in %s',
                                    device_name, filename)
                            definitions['devices'][device_name] = device_def

                    # If we have a dict of device_type definitions, copy them into the
                    # 'device_types' key of our definitions.
                    elif key == 'device_types':
                        if not isinstance(val, dict):
                            logging.error(
                                '"device_typess" values in file %s must be dict. '
                                'Found type "%s"', filename, type(val))
                            return None

                        for device_type_name, device_type_def in val.items():
                            if device_type_name in definitions['device_types']:
                                logging.warning(
                                    'Duplicate definition for "%s" found in %s',
                                    device_type_name, filename)
                            definitions['device_types'][
                                device_type_name] = device_type_def

                    # If we're including other files, recurse inelegantly
                    elif key == 'includes':
                        if not type(val) in [str, list]:
                            logging.error(
                                '"includes" values in file %s must be either '
                                'a list or a simple string. Found type "%s"',
                                filename, type(val))
                            return None

                        if isinstance(val, str):
                            val = [val]
                        for filespec in val:
                            new_defs = self._new_read_definitions(
                                filespec, definitions)
                            definitions['devices'].update(
                                new_defs.get('devices', {}))
                            definitions['device_types'].update(
                                new_defs.get('device_types', {}))

                    # If it's not an includes/devices/device_types def, assume
                    # it's a (deprecated) top-level device or device_type
                    # definition. Try adding it to the right place.
                    else:
                        category = val.get('category', None)
                        if category not in ['device', 'device_type']:
                            logging.warning(
                                'Top-level definition "%s" in file %s is not '
                                'category "device" or "device_type". '
                                'Category is "%s" - ignoring', category)
                            continue
                        if category == 'device':
                            if key in definitions['devices']:
                                logging.warning(
                                    'Duplicate definition for "%s" found in %s',
                                    key, filename)
                            definitions['devices'][key] = val
                        else:
                            if key in definitions['device_types']:
                                logging.warning(
                                    'Duplicate definition for "%s" found in %s',
                                    key, filename)
                            definitions['device_types'][key] = val

        # Finally, return the accumulated definitions
        return definitions
Example #9
0
    def process_command(self, command):
        """Parse and execute the command string we've received."""
        try:
            if not command:
                logging.info('Empty command received')

            # elif command == 'cruises':
            #   cruises = self.api.get_cruises()
            #   if cruises:
            #     print('Loaded cruises: ' + ', '.join(cruises))
            #   else:
            #     print('No cruises loaded')

            # load_cruise <cruise config file name>
            elif command == 'load_configuration':
                raise ValueError(
                    'format: load_configuration <config file name>')
            elif command.find('load_configuration ') == 0:
                (load_cmd, filename) = command.split(maxsplit=1)
                logging.info('Loading config from %s', filename)
                try:
                    config = read_config(filename)
                    self.api.load_configuration(config)
                except FileNotFoundError as e:
                    logging.error('Unable to find file "%s"', filename)

            # set_cruise <JSON encoding of a cruise>
            elif command == 'set_configuration':
                raise ValueError(
                    'format: set_configuration <JSON encoding of config>')
            elif command.find('set_configuration ') == 0:
                (cruise_cmd, config_json) = command.split(maxsplit=1)
                logging.info('Setting config to %s', config_json)
                self.api.load_configuration(json.loads(config_json))

            # delete_cruise <cruise_id>
            # elif command == 'delete_configuration':
            #   raise ValueError('format: delete_configuration')
            elif command.find('delete_configuration') == 0:
                (config_cmd) = command.split(maxsplit=1)
                logging.info('Deleting config')
                self.api.delete_configuration()

            # modes <cruise_id>
            # elif command == 'modes':
            #   raise ValueError('format: modes')
            elif command.find('get_modes') == 0:
                (mode_cmd) = command.split(maxsplit=1)
                modes = self.api.get_modes()
                if len(modes) > 0:
                    print('Available Modes: %s' % (', '.join(modes)))
                else:
                    print('Available Modes: n/a')

            ############################
            # mode <cruise_id>
            # elif command == 'mode':
            #   raise ValueError('format: mode')
            elif command.find('get_active_mode') == 0:
                (mode_cmd) = command.split(maxsplit=1)
                mode = self.api.get_active_mode()
                print('Current mode: %s' % (mode))

            # set_active_mode <mode>
            elif command == 'set_active_mode':
                raise ValueError('format: set_active_mode <mode>')
            elif command.find('set_active_mode ') == 0:
                (mode_cmd, mode_name) = command.split(maxsplit=1)
                logging.info('Setting mode to %s', mode_name)
                self.api.set_active_mode(mode_name)

            ############################
            # loggers <cruise_id>
            # elif command == 'loggers':
            #   raise ValueError('format: loggers')
            elif command.find('get_loggers') == 0:
                (loggers_cmd) = command.split(maxsplit=1)
                loggers = self.api.get_loggers()
                if len(loggers) > 0:
                    print('Loggers: %s' % (', '.join(loggers)))
                else:
                    print('Loggers: n/a')

            ############################
            # logger_configs <cruise_id> <logger>
            elif command == 'get_logger_configs':
                raise ValueError('format: get_logger_configs <logger name>')
            elif command.find('get_logger_configs ') == 0:
                (logger_cmd, logger_name) = command.split(maxsplit=1)
                logger_configs = self.api.get_logger_config_names(logger_name)
                print('Configs for %s: %s' %
                      (logger_name, ', '.join(logger_configs)))

            ############################
            # set_logger_config_name <cruise_id> <logger name> <name of logger config>
            elif command == 'set_active_logger_config':
                raise ValueError(
                    'format: set_active_logger_config <logger name> <name of logger config>'
                )
            elif command.find('set_active_logger_config ') == 0:
                (logger_cmd, logger_name,
                 config_name) = command.split(maxsplit=2)
                logging.info('Setting logger %s to config %s', logger_name,
                             config_name)

                # Is this a valid config for this logger?
                if not config_name in self.api.get_logger_config_names(
                        logger_name):
                    raise ValueError(
                        'Config "%s" is not valid for logger "%s"' %
                        (config_name, logger_name))
                self.api.set_active_logger_config(logger_name, config_name)

            ############################
            # configs <cruise_id>
            # elif command == 'configs':
            #   raise ValueError('format: configs')
            elif command.find('get_active_logger_configs') == 0:
                (config_cmd) = command.split(maxsplit=1)
                config_names = {
                    logger_id: self.api.get_logger_config_name(logger_id)
                    for logger_id in self.api.get_loggers()
                }
                if len(config_names) > 0:
                    for logger_id, config_name in config_names.items():
                        print('%s: %s' % (logger_id, config_name))
                else:
                    print("No configs found!")

            ############################
            # status
            # elif command == 'status':
            #   raise ValueError('format: status')
            elif command.find('get_status') == 0:
                (status_cmd) = command.split(maxsplit=1)
                status_dict = self.api.get_status()
                print('%s' % pprint.pformat(status_dict))

            ############################
            # status_since
            elif command == 'get_status_since':
                raise ValueError('format: get_status_since <timestamp>')
            elif command.find('get_status_since ') == 0:
                (status_cmd, since_timestamp) = command.split(maxsplit=1)
                status_dict = self.api.get_status(float(since_timestamp))
                print('%s' % pprint.pformat(status_dict))

            ############################
            # server_log
            elif command == 'get_server_log':
                server_log = self.api.get_message_log(source=SOURCE_NAME)
                print('%s' % pprint.pformat(server_log))

            ############################
            # server_log timestamp
            elif command.find('get_server_log') == 0:
                (log_cmd, since_timestamp) = command.split(maxsplit=1)
                server_log = self.api.get_message_log(
                    source=SOURCE_NAME,
                    user=None,
                    log_level=self.api.DEBUG,
                    since_timestamp=float(since_timestamp))
                print('%s' % pprint.pformat(server_log))

            ############################
            # Quit gracefully
            elif command == 'quit':
                logging.info('Got quit command')
                self.quit()

            ############################
            elif command == 'help':
                self.show_commands()

            ############################
            else:
                print('Got unknown command: "{}"'.format(command))
                print('Type "help" for help')

        except ValueError as e:
            logging.error('%s', e)
        finally:
            self.api.message_log(source=SOURCE_NAME,
                                 user='******' % (USER, HOSTNAME),
                                 log_level=self.api.INFO,
                                 message='command: ' + command)
Example #10
0
def index(request):
    """Home page - render logger states and cruise information.
    """
    global api
    if api is None:
        api = DjangoServerAPI()

    ############################
    # If we've gotten a POST request
    # cruise_id = ''
    errors = []
    if request.method == 'POST':
        logging.debug('POST: %s', request.POST)

        # First things first: log the request
        log_request(request, 'index')

        # Are they deleting a cruise?(!)
        if 'delete_cruise' in request.POST:
            logging.info('deleting cruise')
            api.delete_cruise()

        # Did we get a mode selection?
        elif 'select_mode' in request.POST:
            new_mode_name = request.POST['select_mode']
            logging.info('switching to mode "%s"', new_mode_name)
            try:
                api.set_active_mode(new_mode_name)
            except ValueError as e:
                logging.warning('Error trying to set mode to "%s": %s',
                                new_mode_name, str(e))

        elif 'reload_button' in request.POST:
            logging.info('reloading current configuration file')
            try:
                cruise = api.get_configuration()
                filename = cruise['config_filename']

                # Load the file to memory and parse to a dict. Add the name
                # of the file we've just loaded to the dict.
                config = read_config(filename)
                if 'cruise' in config:
                    config['cruise']['config_filename'] = filename
                api.load_configuration(config)
            except ValueError as e:
                logging.warning('Error reloading current configuration: %s',
                                str(e))

        # If they canceled the upload
        elif 'cancel' in request.POST:
            logging.warning('User canceled upload')

        # Else unknown post
        else:
            logging.warning('Unknown POST request: %s', request.POST)

    # Assemble information to draw page
    template_vars = {
        'websocket_server': WEBSOCKET_DATA_SERVER,
        'errors': {
            'django': errors
        },
    }
    try:
        configuration = api.get_configuration()
        template_vars['cruise_id'] = configuration.get('id', 'Cruise')
        template_vars['filename'] = configuration.get('config_filename',
                                                      '-none-')
        template_vars['loggers'] = api.get_loggers()
        template_vars['modes'] = api.get_modes()
        template_vars['active_mode'] = api.get_active_mode()
        template_vars['errors'] = errors
    except (ValueError, AttributeError):
        logging.info('No configuration loaded')

    return render(request, 'django_gui/index.html', template_vars)
Example #11
0
                        action='count',
                        help='Increase output verbosity of component loggers')

    args = parser.parse_args()

    # Set up logging first of all
    LOG_LEVELS = {0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG}
    log_level = LOG_LEVELS[min(args.verbosity, max(LOG_LEVELS))]
    if args.stderr_file:
        stderr_writers = [TextFileWriter(args.stderr_file)]
        logging.getLogger().addHandler(StdErrLoggingHandler(stderr_writers))

    # What level do we want our component loggers to write?
    logger_log_level = LOG_LEVELS[min(args.logger_verbosity, max(LOG_LEVELS))]

    configs = read_config(args.config) if args.config else None

    # If they've specified a mode, see if what we've read in is in fact
    # a cruise definition with modes we can choose from.
    if args.mode:
        modes = configs.get('modes', None)
        if not modes:
            logging.fatal('--mode specified, but "%s" has no modes' %
                          args.config)
            sys.exit(1)
        logger_configs = configs.get('configs', None)
        if not logger_configs:
            logging.fatal('File "%s" has no logger configs?' % args.config)
            sys.exit(1)

        # What are the names of the logger configs for the requested mode?