saltstack源码-启动3-config.py配置文件加载

#目标文件位置/usr/lib/python2.6/site-packages/salt/config.py
#这个文件加载配置文件的模块.master和minion的配置文件加载都是在这个模块里面完成的
#master的启动在这模块里面只涉及到方法和属性只有几个

master和minion的默认配置属性也在这个文件里面定义

DEFAULT_MASTER_OPTS = {
    'interface': '0.0.0.0',
    'publish_port': '4505',
    'pub_hwm': 1000,
    'auth_mode': 1,
    'user': 'root',
    'worker_threads': 5,
    'sock_dir': os.path.join(salt.syspaths.SOCK_DIR, 'master'),
    'ret_port': '4506',
    'timeout': 5,
    'keep_jobs': 24,
    'root_dir': salt.syspaths.ROOT_DIR,
    'pki_dir': os.path.join(salt.syspaths.CONFIG_DIR, 'pki', 'master'),
    'cachedir': os.path.join(salt.syspaths.CACHE_DIR, 'master'),
    'file_roots': {
        'base': [salt.syspaths.BASE_FILE_ROOTS_DIR],
    },
    'master_roots': {
        'base': [salt.syspaths.BASE_MASTER_ROOTS_DIR],
    },
    'pillar_roots': {
        'base': [salt.syspaths.BASE_PILLAR_ROOTS_DIR],
    },
    'gitfs_remotes': [],
    'gitfs_root': '',
    'gitfs_base': 'master',
    'hgfs_remotes': [],
    'hgfs_root': '',
    'hgfs_base': 'default',
    'hgfs_branch_method': 'branches',
    'svnfs_remotes': [],
    'svnfs_root': '',
    'ext_pillar': [],
    'pillar_version': 2,
    'pillar_opts': True,
    'peer': {},
    'syndic_master': '',
    'runner_dirs': [],
    'outputter_dirs': [],
    'client_acl': {},
    'client_acl_blacklist': {},
    'external_auth': {},
    'token_expire': 43200,
    'file_recv': False,
    'file_buffer_size': 1048576,
    'file_ignore_regex': None,
    'file_ignore_glob': None,
    'fileserver_backend': ['roots'],
    'fileserver_followsymlinks': True,
    'fileserver_ignoresymlinks': False,
    'fileserver_limit_traversal': False,
    'max_open_files': 100000,
    'hash_type': 'md5',
    'conf_file': os.path.join(salt.syspaths.CONFIG_DIR, 'master'),
    'open_mode': False,
    'auto_accept': False,
    'renderer': 'yaml_jinja',
    'failhard': False,
    'state_top': 'top.sls',
    'master_tops': {},
    'external_nodes': '',
    'order_masters': False,
    'job_cache': True,
    'ext_job_cache': '',
    'master_ext_job_cache': '',
    'minion_data_cache': True,
    'enforce_mine_cache': False,
    'ipv6': False,
    'log_file': os.path.join(salt.syspaths.LOGS_DIR, 'master'),
    'log_level': None,
    'log_level_logfile': None,
    'log_datefmt': _DFLT_LOG_DATEFMT,
    'log_datefmt_logfile': _DFLT_LOG_DATEFMT_LOGFILE,
    'log_fmt_console': _DFLT_LOG_FMT_CONSOLE,
    'log_fmt_logfile': _DFLT_LOG_FMT_LOGFILE,
    'log_granular_levels': {},
    'pidfile': os.path.join(salt.syspaths.PIDFILE_DIR, 'salt-master.pid'),
    'publish_session': 86400,
    'cluster_masters': [],
    'cluster_mode': 'paranoid',
    'range_server': 'range:80',
    'reactor': [],
    'serial': 'msgpack',
    'state_verbose': True,
    'state_output': 'full',
    'state_auto_order': True,
    'state_events': False,
    'search': '',
    'search_index_interval': 3600,
    'loop_interval': 60,
    'nodegroups': {},
    'cython_enable': False,
    'enable_gpu_grains': False,
    # XXX: Remove 'key_logfile' support in 2014.1.0
    'key_logfile': os.path.join(salt.syspaths.LOGS_DIR, 'key'),
    'verify_env': True,
    'permissive_pki_access': False,
    'default_include': 'master.d/*.conf',
    'win_repo': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR, 'win', 'repo'),
    'win_repo_mastercachefile': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR,
                                             'win', 'repo', 'winrepo.p'),
    'win_gitrepos': ['https://github.com/saltstack/salt-winrepo.git'],
    'syndic_wait': 1,
    'jinja_lstrip_blocks': False,
    'jinja_trim_blocks': False,
    'sign_pub_messages': False,
    'keysize': 4096,
    'salt_transport': 'zeromq',
    'gather_job_timeout': 2,
    'enumerate_proxy_minions': False,
    'ssh_passwd': '',
    'ssh_port': '22',
    'ssh_sudo': False,
    'ssh_timeout': 60,
    'ssh_user': 'root',
}

这个字典主要是定义的master的默认配置
具体的自己去看syspaths.py和/etc/salt/master
master启动的时候配置文件调用的方法

def master_config(path, env_var='SALT_MASTER_CONFIG', defaults=None):
    '''
    Reads in the master configuration file and sets up default options
    '''
    if defaults is None:
        defaults = DEFAULT_MASTER_OPTS #默认配置选项
 
    if not os.environ.get(env_var, None):#这里取的是反值
        # No valid setting was given using the configuration variable.
        # Lets see is SALT_CONFIG_DIR is of any use
        salt_config_dir = os.environ.get('SALT_CONFIG_DIR', None)
        #启动初始化的时候是继承系统的环境变量,所以SALT_CONFIG_DIR变量是不存在的, 
        if salt_config_dir:
            env_config_file_path = os.path.join(salt_config_dir, 'master')
            if salt_config_dir and os.path.isfile(env_config_file_path):
                # We can get a configuration file using SALT_CONFIG_DIR, let's
                # update the environment with this information
                os.environ[env_var] = env_config_file_path
 
    overrides = load_config(path, env_var, DEFAULT_MASTER_OPTS['conf_file'])
    #load_config(path='/etc/salt/master',env_var='SALT_MASTER_CONFIG',default_path=/etc/salt/master'')
    #返回值和属性是配置文件的不是默认的
    default_include = overrides.get('default_include',
                                    defaults['default_include'])
    include = overrides.get('include', [])
 
    overrides.update(include_config(default_include, path, verbose=False))
    overrides.update(include_config(include, path, verbose=True))
    #这2个update目前还没添加任何的配置属性和值
    opts = apply_master_config(overrides, defaults) #这个把配置文件的选项和值覆盖掉默认的,顺便添加几个选项
    _validate_opts(opts) #这个主要是验证,配置是否正确的类型
    # If 'nodegroups:' is uncommented in the master config file, and there are
    # no nodegroups defined, opts['nodegroups'] will be None. Fix this by
    # reverting this value to the default, as if 'nodegroups:' was commented
    # out or not present.
    if opts.get('nodegroups') is None:
        opts['nodegroups'] = DEFAULT_MASTER_OPTS.get('nodegroups', {})
    return opts  

配置文件的加载读取方法,这2个方法master和minion都会用到,minion我就暂时不管了
暂时只要知道这个方法是加载读取配置文件的就行

def load_config(path, env_var, default_path=None):
    '''
    Returns configuration dict from parsing either the file described by
    ``path`` or the environment variable described by ``env_var`` as YAML.
    '''
    if path is None:
        # When the passed path is None, we just want the configuration
        # defaults, not actually loading the whole configuration.
        return {}
 
    if default_path is None: #
        # This is most likely not being used from salt, ie, could be salt-cloud
        # or salt-api which have not yet migrated to the new default_path
        # argument. Let's issue a warning message that the environ vars won't
        # work.
        import inspect
        previous_frame = inspect.getframeinfo(inspect.currentframe().f_back)
        log.warning(
            'The function \'{0}()\' defined in {1!r} is not yet using the '
            'new \'default_path\' argument to `salt.config.load_config()`. '
            'As such, the {2!r} environment variable will be ignored'.format(
                previous_frame.function, previous_frame.filename, env_var
            )
        )
        # In this case, maintain old behaviour
        default_path = DEFAULT_MASTER_OPTS['conf_file']
 
    # Default to the environment variable path, if it exists
    env_path = os.environ.get(env_var, path) #这里把path的值赋予env_path
    if not env_path or not os.path.isfile(env_path):
        env_path = path
    # If non-default path from `-c`, use that over the env variable
    if path != default_path:
        env_path = path
 
    path = env_path
 
    # If the configuration file is missing, attempt to copy the template,
    # after removing the first header line.
    if not os.path.isfile(path):
        template = '{0}.template'.format(path)
        if os.path.isfile(template):
            log.debug('Writing {0} based on {1}'.format(path, template))
            with salt.utils.fopen(path, 'w') as out:
                with salt.utils.fopen(template, 'r') as ifile:
                    ifile.readline()  # skip first line
                    out.write(ifile.read())
 
    if salt.utils.validate.path.is_readable(path):#这里调用的方法是判断是否为文件和可读的属性
        opts = _read_conf_file(path)  #获得配置文件的属性和值
        opts['conf_file'] = path     #这里是设置默认配置文件路径
        return opts           #返回配置文件的属性和值
 
    log.debug('Missing configuration file: {0}'.format(path))
    return {}

读取的方法

def _read_conf_file(path):
    log.debug('Reading configuration from {0}'.format(path))
    with salt.utils.fopen(path, 'r') as conf_file:
        try:
            conf_opts = yaml.safe_load(conf_file.read()) or {} #读取配置文件的属性和值
        except yaml.YAMLError as err:
            log.error(
                'Error parsing configuration file: {0} - {1}'.format(path, err)
            )
            conf_opts = {}
        # only interpret documents as a valid conf, not things like strings,
        # which might have been caused by invalid yaml syntax
        if not isinstance(conf_opts, dict):
            log.error(
                'Error parsing configuration file: {0} - conf should be a '
                'document, not {1}.'.format(path, type(conf_opts))
            )
            conf_opts = {}
        # allow using numeric ids: convert int to string
        if 'id' in conf_opts:  #这条判断语句目前暂时只有minion会用的,master配置文件暂时还没用到id选项
            conf_opts['id'] = str(conf_opts['id'])
        for key, value in conf_opts.copy().iteritems():
            if isinstance(value, unicode):  #判断属性值是否为unicode类型
                # We do not want unicode settings
                conf_opts[key] = value.encode('utf-8')
        return conf_opts  #返回配置文件的属性和值的字典

还有个apply_master_config方法,

def apply_master_config(overrides=None, defaults=None):
    '''
    Returns master configurations dict.
    '''
    if defaults is None:
        defaults = DEFAULT_MASTER_OPTS
 
    opts = defaults.copy()
    if overrides:
        opts.update(overrides)  #使用配置文件选项覆字典盖掉默认的选项
 
    if len(opts['sock_dir']) > len(opts['cachedir']) + 10:
        opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix')
 
    opts['aes'] = salt.crypt.Crypticle.generate_key_string()  
    #这里是添加一个aes键作为配置选项,它的默认值默认是随机返回一个56位byte值的base64解码表示
    #一看就知道是加密用的
    opts['extension_modules'] = (
        opts.get('extension_modules') or
        os.path.join(opts['cachedir'], 'extmods')
    )
    #添加一个extension_modules键 值是/var/cache/salt/extmods
    opts['token_dir'] = os.path.join(opts['cachedir'], 'tokens')
    #添加一个token_dir键 值是/var/cache/salt/tokens
 
    # Prepend root_dir to other paths
    prepend_root_dirs = [
        'pki_dir', 'cachedir', 'pidfile', 'sock_dir', 'extension_modules',
        'autosign_file', 'autoreject_file', 'token_dir'
    ]
 
    # These can be set to syslog, so, not actual paths on the system
    for config_key in ('log_file', 'key_logfile'):
        log_setting = opts.get(config_key, '')
        if log_setting is None:
            continue
 
        if urlparse.urlparse(log_setting).scheme == '':
            prepend_root_dirs.append(config_key)
    #向列表里面再添加2个元素 'log_file','key_logfile'
 
 
    prepend_root_dir(opts, prepend_root_dirs)
    #这个函数只要是起规范路径的作用..
    # Enabling open mode requires that the value be set to True, and
    # nothing else!
    opts['open_mode'] = opts['open_mode'] is True
    opts['auto_accept'] = opts['auto_accept'] is True
    opts['file_roots'] = _validate_file_roots(opts)
 
    if opts['file_ignore_regex']:
        # If file_ignore_regex was given, make sure it's wrapped in a list.
        # Only keep valid regex entries for improved performance later on.
        if isinstance(opts['file_ignore_regex'], str):
            ignore_regex = [opts['file_ignore_regex']]
        elif isinstance(opts['file_ignore_regex'], list):
            ignore_regex = opts['file_ignore_regex']
 
        opts['file_ignore_regex'] = []
        for regex in ignore_regex:
            try:
                # Can't store compiled regex itself in opts (breaks
                # serialization)
                re.compile(regex)
                opts['file_ignore_regex'].append(regex)
            except Exception:
                log.warning(
                    'Unable to parse file_ignore_regex. Skipping: {0}'.format(
                        regex
                    )
                )
 
    if opts['file_ignore_glob']:
        # If file_ignore_glob was given, make sure it's wrapped in a list.
        if isinstance(opts['file_ignore_glob'], str):
            opts['file_ignore_glob'] = [opts['file_ignore_glob']]
 
    # Let's make sure `worker_threads` does not drop bellow 3 which has proven
    # to make `salt.modules.publish` not work under the test-suite.
    if opts['worker_threads'] < 3 and opts.get('peer', None):
        log.warning(
            'The \'worker_threads\' setting on {0!r} cannot be lower than 3. '
            'Resetting it to the default value of 3.'.format(
                opts['conf_file']
            )
        )
        opts['worker_threads'] = 3
    return opts

 

posted @ 2014-09-24 02:05  ppingg  阅读(1804)  评论(0编辑  收藏  举报