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