keystone-all 代码分析

<keystone name="keystone-all">
    <possible_topdir path="/keystone/keystone/cmd/all.py" function="初始化服务器">
         possible_dir = os.path.normpath(os.path.join(os.path.abspath(__file__),
                                       os.pardir,
                                       os.pardir,
                                       os.pardir)))
         if os.path.exists(os.path.join(possible_topdir,
                                            'keystone',
                                            '__init__.py')))
             sys.path.insert(0,  possible_topdir)):
            from keystone.server import eventlet as eventlet_server
            def main():
                eventlet_server.run(possible_dir)
                <eventlet_server.run path="/keystone/keystone/server/eventlet.py" function="启动服务器">
                    def run(possible_dir):
                        join = os.path.join(possible_topdir, 'etc', 'keystone.conf') # join = '/etc/keystone/keystone.conf'
                        dev_conf = join
                        config_files = None
                        if os.path.exists(dev_conf): # 如果存在 join这一配置文件
                            config_files = [dev_conf] # 将配置文件装入列表,赋值给config_files
                            common.configure(
                                version=pbr.version.VersionInfo('keystone').version_string(),
                                config_files=config_files,
                                pre_setup_logging_fn=configure_threading)
                            <common.configure path="/keystone/keystone/server/common.py" function="配置与sql初始化">


                                from oslo_config import cfg
                                from keystone.common import dependency
                                from keystone.common import sql
                                from keystone import config
                                from keystone.server import backends
                                CONF = cfg.CONF # keystone代码中几乎都import cfg库,但是只实例化一次,因为CONF=ConfigOpts import一次

                                def configure(version=None, conf_files=None, pre_setup_logging_fn=lambda: None):
                                    config.configure()
                                    <config.configure name="config.configure()" path="/keystone/keystone/config.py" alias="配置选项">
                                        from oslo_config import cfg
                                        configure = config.configure
                                        <configre name="configure=config.configure" path="/keystone/keystone/common/config.py">
                                            from keystone.common import config
                                            def configure(conf=None):
                                                if conf is None:
                                                    conf = CONF
                                                conf.register_cli_opt(
                                                    cfg.BoolOpt('standard-threads', default=False,
                                                        help='Do not monkey-patch threading system modules.'))
                                                conf.register_cli_opt(
                                                    cfg.StrOPt('pydev-debug-host',
                                                                help='Host to connect to for remote debugger.'))
                                                conf.register_cli_opt(
                                                    cfg.IntOpt('pydev-debug-port',
                                                                help='Port to connect to for remote debugger.'))
                                                    <conf.register_cli_opt>


                                                        CONF = ConfigOpts()
                                                        conf=CONF
                                                        class ConfigOpts(collections.Mapping):
                                                            # 需要了解collections.Mapping
                                                            def __init__(self):
                                                                self._opts = {}
                                                                self._groups = {}
                                                                self._args = None
                                                                self._oparser = None
                                                                self._namespace = None
                                                                self.__cache = {}
                                                                self._config_opts = []
                                                                self._cli_opts = collections.deque()
                                                                self._validate_default_values = False

                                                            def __clear_cache(f) # 只是将self.__cache.clear()
                                                                @functools.wraps(f) # 被装饰的f可以保留自身属性
                                                                def __inner(self, *args, **kwargs):
                                                                    if kwargs.pop('clear_cache', True):
                                                                    # 只要加了这个装饰器,除非传入参数clear_cache=False,
                                                                    # 否则都需要clear
                                                                        result = f(self, *args, **kwargs)
                                                                        self.__cache.clear()
                                                                        return result
                                                                    esle:
                                                                        return f(self, *args, **kwargs)
                                                                return __inner

                                                            @__clear_cache
                                                            def register_cli_opts(self, opts, group=None):
                                                                for opt in opts:
                                                                    self.register_cli_opt(opt, group, clear_cache=False)
                                                                    # 注意 clear_cache=False

                                                            @__clear_cache
                                                            def register_cli_opt(self, opt, group=None):
                                                                # self._args = None
                                                                # CLI 选项必须在命令行和配置文件被解析前注册好,这样可以确保--help等的正常使用
                                                                if self._args is not None:
                                                                    raise ArgsAlreadyParsedError("cannot register CLI
                                                                            option.")
                                                                return self.register_opt(opt, group, cli=True, clear_cache=False)
                                                            @__clear_cache
                                                            def register_opt(self, opt, group=None, cli=False):
                                                                if group is not None:
                                                                    group = self._get_group(group, autocreate=True)
                                                                    <group name="self._get_group(group, autocreate=True)" alias="取得OptGroup">
                                                                        def _get_group(self, group_or_name, autocreate=False):
                                                                            # autocreate=False 如果为True则会创建GroupOpt实例
                                                                            group = group_or_name if isinstance(group_or_name, OptGroup) else None
                                                                            # 如果group_or_name 是实例则返回group_or_name 否则返回None
                                                                            group_name = group.name if group else group_or_name
                                                                            # 如果group不为空,则返回group.name否则返回group_or_name
                                                                            if group_name not in self._groups:
                                                                                # 如果group_name不在self._groups中
                                                                                if not autocreate:
                                                                                    # 如果autocreate=False
                                                                                    raise NoSuchError(group_name)
                                                                                self.register_group(group or OptGroup(name=group_name))
                                                                                <register_group name="self.register_group(group or OptGroup(name=group_name))">
                                                                                    def register_group(self, group):
                                                                                        # group是OptGroup实例
                                                                                        # group befor options register
                                                                                        if group.name in self._groups: # self._groups = {}
                                                                                            return
                                                                                        self._groups[group.name] = copy.copy(group)





                                                                                </register_group>
                                                                                <OptGroup name="OptGroup(name=group_name)">
                                                                                    class OptGroup(object):
                                                                                        def __init__(self, name, title=None, help=None):
                                                                                            self.name = name
                                                                                            self.title = '%s options' % name if title is None else title
                                                                                            self.help = help
                                                                                            self._opts = {}
                                                                                            self._argparse_group = None
                                                                                </OptGroup>
                                                                            return self._groups[group_name] # 返回的是OptGroup实例





                                                                    </group>
                                                                    if cli:
                                                                        self._add_cli_opt(opt, group)
                                                                        <self._add_cli_opt name="self._add_cli_opt(opt, group)" path="cfg.ConfigOpts">
                                                                            def _add_cli_opt(self, opt, group):
                                                                                if {'opt': opt, 'group': group} in self._cli_opts:
                                                                                    return
                                                                                if opt.positional: # self._cli_opts collections.deque()
                                                                                    # 有放置要求时候
                                                                                    self._cli_opts.append({'opt': opt, 'group': group})
                                                                                else:
                                                                                    self._cli_opts.appendleft({'opt': opt, 'group': group})


                                                                        </self._add_cli_opt>
                                                                    return group._register_opt(opt, cli)
                                                                    <group._register_opt name="group._register_opt(opt, cli)" path="cfg.OptGroup">
                                                                       def _register_opt(self, opt, cli=False):
                                                                            # cli:是否为cli option
                                                                            if _is_opt_registered(self._opts, opt):
                                                                                <_register_opt name="_is_opt_registered(self._opts, opt)" path="cfg">
                                                                                    def _is_opt_registered(opts, opt):
                                                                                        if opt.dest in opts:
                                                                                            if opts[opt.dest]['opt'] !=opt
                                                                                                raise DuplicateOptError(opt.name)
                                                                                            return True
                                                                                        else:
                                                                                            return False


                                                                                </_register_opt>
                                                                                return False
                                                                            self._opts[opt.dest] = {'opt': opt, 'cli': cli}
                                                                            return True

                                                                    </group._register_opt>
                                                                if cli:
                                                                    self._add_cli_opt(opt, None)
                                                                if _is_opt_registered(self._opts, opt):
                                                                    return False
                                                                self._opts[opt.dest] = {'opt': opt, 'cli': cli}
                                                                return True










                                                    </conf.register_cli_opt>
                                            for section in FILE_OPTIONS:
                                                for option in FILE_OPTIONS[section]:
                                                    # FILE_OPTIONS 在keystone.common.config 是字典
                                                    # 此操作是将options都注册进ConfigOpts实例中
                                                    if section:
                                                        conf.register_opt(option, group=section)
                                                    else:
                                                        conf.register_opt(option)

                                            setup_authentication(conf)
                                            <setup_authentication values="conf" path="keystone.common.config" function="">
                                                def setup_authentication(conf=None): conf=CONF
                                                    if conf is None:
                                                        for method_name in conf.auth.methods:
                                                            # conf.auth.methods 默认就是下面的
                                                            if method_name not in _DEFAULT_AUTH_METHODS:
                                                                # _DEFAULT_AUTH_METHODS = ['external', 'password', 'token', 'oauth1']
                                                                option = cfg.StrOpt(method_name)

                                                                _register_auth_plugin_opt(conf, option)
                                                                <_register_auth_plugin_opt vlues="(conf, option)" path="">
                                                                    def _register_auth_plugin_opt(conf, option):
                                                                        conf.register_opt(option, group='auth')
                                                                </_register_auth_plugin_opt>



                                            </setup_authentication>
                                        </configre>

                                    </config.configure>
                                sql.initialize()
                                <sql.initializa name="sql.initializa()" path="keyston.common.sql.core" function="sql初始化工作">
                                    from oslo_config import cfg
                                    from oslo_db import options as db_options
                                    CONF = cfg.CONF
                                    LOG = log.getLogger(__name__)
                                    def initialize():
                                        db_options.set_defaults(
                                            CONF,
                                            connections="sqlite:///keystone.db")
                                        <db_options.set_defaults path="oslo_db.options" name="db_options.set_defaults(CONF, connections='sqlite:///keystone.db')">
                                            def set_defaults(conf, connection=None, sqlite_db=None,
                                                            max_pool_size=None, max_overflow=None,
                                                            pool_timeout=None):
                                                # 设置默认配置,覆盖以前默认值
                                                conf.register_opts(database_opts, group='database')

                                                if connection is not None:
                                                    conf.set_default('connection', connection, group='database')
                                                if sqlite_db is not None:
                                                    conf.set_default('sqlite_db', sqlite_db, group='database')
                                                if max_pool_size is not None:
                                                    conf.set_default('max_pool_size', max_pool_size, group='database')
                                                if max_overflow is not None:
                                                    conf.set_default('max_overflow', max_overflow, group='database')
                                                if pool_timeout is not None:
                                                    conf.set_default('pool_timeout', pool_timeout, group='database')
                                                    <conf.setdefault path='oslo_config.cfg.ConfigOpts' name="conf.setdefault('pool_timeout', pool_timeout, group='database')">
                                                        @__clear_cache
                                                        def set_default(self, name, default, group=None):
                                                            # name: dest/name
                                                            # group: GroupOpt/ group name
                                                            opt_info = self._get_opt_info(name, group)
                                                            opt_info['default'] = default
                                                            <self._get_opt_info name="self._get_opt_info(name, group)">
                                                                # 返回 (opt, override, default)
                                                                if group is None:
                                                                    opts = self._opts
                                                                else:
                                                                    group = self._get_group(group)
                                                                    opts = group._opts
                                                                if opt_name not in opts:
                                                                    raise NoSuchOptError(opt_name, group)
                                                                return opts[opt_name]


                                                            </self._get_opt_info>
                                                    </conf.setdefault>
                                        </db_options.set_defaults>

                                </sql.initializa>
                                CONF(project='keystone', version=version, default_config_files=config_files)
                                <CONF path='oslo_config.cfg.ConfigOpts' name="CONF(project='keystone', version=version, default_config_files=config_files)">
                                    def __call__(self, args=None,
                                                project=None, # 'keystone'
                                                prog=None,
                                                version=None, # pbr.version...
                                                usage=None,
                                                default_config_files=None, # keystone.conf
                                                validate_default_values=False):
                                        # 解析命令行参数与配置文件
                                        # 将参数实例成属性
                                        # args: 命令行参数 argv[1:]
                                        # project: 顶级的项目名称,这里是keystone,用于定位配置文件
                                        # prog: 程序名 默认为 sys.argv[0] basename
                                        # version: 程序版本
                                        # usage: 用法
                                        # default_config_files: 默认使用的配置文件
                                        # validate_default_values: 默认值是否合法
                                        # return: 解析后剩余选项列表

                                        self.clear()
                                        <self.clear name="self.clear()">
                                            @__clear_cache
                                            def clear(self):
                                               # 任何使用add_cli_subparsers()添加的subparsers都会被remove,这是副作用
                                                self._args = None
                                                self._oparser = None
                                                self._namespace = None
                                                self._validate_default_values = False

                                                self.unregister_opts(self._config_opts)
                                                <self.unregister_opts name="self.unregister_opts(self._config_opts)">
                                                    @__clear_cache
                                                    def unregister_opts(self, opts, group=None):
                                                        for opt in opts:

                                                            self.unregister_opt(opt, group, clear_cache=False)
                                                            <self.unregister_opt name="self.unregister_opt(opt, group, clear_cache=False)">
                                                                @__clear_cache
                                                                def unregister_opt(self, opt, group=None):
                                                                    if self._args is not None:
                                                                    # self._args 是命令行参数
                                                                        raise ArgsALreadyParsedError("reset before unregistering options")
                                                                remitem = None
                                                                for item in self._cli_opts:
                                                                # self._cli_opts.append({'opt':opt, 'group': group})
                                                                    if (item['opt'].dest == opt.dest and
                                                                        (group is None or
                                                                            self._get_group(group).name == item['group'].name)):
                                                                        remitem = item
                                                                        break
                                                                if remitem is not None:
                                                                    self._cli_opts.remove(remitem)


                                                            </self.unregister_opt>


                                                </self.unregister_opts>
                                                for group in self._group.values():

                                                    group._clear()
                                                    <group._clear path="oslo_config.cfg.OptGroup">
                                                        def _clear(self):
                                                            # 清楚group 选项的解析状态

                                                            self._argparse_group = None
                                                            <self._argparse_group name="self._argparse_group = None">
                                                                def _get_argparse_group(self, parser):
                                                                    if self._argparse_group is None:
                                                                        self._argparse_group = parser.add_argument_group(
                                                                                                    self.title,
                                                                                                    self.help)
                                                                        return self._argparse_group

                                                            </self._argparse_group>

                                                    </group._clear>

                                        </self.clear>

                                        self._validate_default_values = validate_default_values

                                        prog, default_config_files = self._pre_setup(project,
                                                                                    prog,
                                                                                    version,
                                                                                    usage,
                                                                                    default_config_files)
                                        <self._pre_setup name="prog, default_config_files = self._pre_setup()">
                                            def _pre_setup(self, project, prog, version, usage, default_config_files):
                                                # project=keystone, version=pbr.version...
                                                # default_config_files=['/etc/keystone/keystone.conf',]
                                                # 为解析选项初始化一个ConfigCliParser
                                                if prog is None:
                                                    prog = os.path.basename(sys.argv[0]) # 第一个参数(即程序)赋值给prog
                                                if default_config_files is None:

                                                    default_config_files = find_config_files(project, prog)
                                                    <find_config_files path='oslo_config.cfg' name="default_config_files = find_config_files(project, prog)">
                                                        def find_config_files(project=None, prog=None, extension='.conf'):
                                                            # 在 ~/.${project}/ 、 ~/、/etc/${project}/、/etc/中查找配置文件
                                                            # 返回最高目录下的配置文件的绝对路径
                                                            # 如果没有项目名,则我们找寻${prog.conf}
                                                            if prog is None:
                                                                prog = os.path.basename(sys.argv[0])

                                                            cfg_dirs = _get_config_dirs(project)
                                                            <cfg_dirs name="cfg_dirs = _get_config_dirs(project)">
                                                                def _get_config_dirs(projects=None):
                                                                    # 返回~/.${project}/ 、 ~/、/etc/${project}/、/etc/
                                                                    # 如果没有指定project,则返回~/、/etc/
                                                                    cfg_dirs = [
                                                                        _fixpath(os.path.join('~', '.'+)) if project else None,
                                                                        _fixpath('~'),
                                                                        <_fixpath name="_fixpath(os.path.join('~', '.'+)) if project else None">
                                                                            def _fixpath(p):
                                                                                # p 应当为~user或者为~,其他无用
                                                                                #返回p的绝对路径
                                                                                return os.path.abspath(os.path.expanduser(p))

                                                                        </_fixpath>
                                                                        os.path.join('/etc', project) if project else None
                                                                        '/etc'
                                                                    ]
                                                                    return list(moves.filter(bool, cfg_dirs))
                                                                    # from six import moves


                                                            </cfg_dirs>
                                                    </find_config_files>

                                                    self._oparser = _CachedArgumentParser(prog=prog, usage=usage)
                                                    <self.oparser path="oslo_config.cfg" name="self._oparser=_CachedArgumentParser(prog=prog, usage=usage)">
                                                        class _CachedAgurumentParser(argument.ArgumentParser):
                                                            # caching/collectiong 命令行参数
                                                            # 在初始化ArgumentParser之前,给参数排序

                                                    </self.oparser>

                                                    self._oparser.add_parser_argument(self._oparser,
                                                                                        '--version',
                                                                                        action='version',
                                                                                        version=version)
                                                    <add_parser-argument path="oslo_config.cfg._CachedArgumentParser" name="self._oparser.add_parser_argument">
                                                        def add_parser_argument(self, container, *args, **kwargs):
                                                            values = []
                                                            if container in self._args_cache:
                                                                values = self._args_cache[container]
                                                            values.append({'args': args, 'kwargs': kwargs})
                                                            self._args_cache[container] = values
                                                            # self._args_cache['--version'] = values.append({'arg': args, 'kwargs': kwargs})
                                                    </add_parser-argument>
                                                    return prog, default_config_files
                                                    # prog if prog else os.path.basename(sys.argv[0])
                                                    # default_config_files if default_config_files else find_config_files(project, prog)
                                        </self._pre_setup>

                                        self._setup(project, prog, version, usage, default_config_files)
                                        <self._setup name="self._setup(project, prog, version, usage, default_config_files)">
                                            def _setup(self, project, prog, version, usage, default_config_files):
                                                # 为选项的解析而进程初始化ConfigOpts实例
                                                self._config_opts = [
                                                    _ConfigFileOpts('config-file',
                                                                    default_config_files,
                                                                    metavar='PATH',
                                                                    help=('Path to a config file to use. Multiple '
                                                                            'config files can be specified, with values '
                                                                            'in later files taking precedence. The '
                                                                            'default files used are: %(default)s.')),
                                                    _ConfigDirOpt('config-dir',
                                                                    metavar='DIR',
                                                                    help='Path to a config directory to pull *.conf '
                                                                    'files from. This file set is sorted, so as to '
                                                                    'provide a predictable parse order if '
                                                                    'is parsed after the file(s) specified via '
                                                                     'previous --config-file, arguments hence '
                                                                    'over-ridden options in the directory take '
                                                                    'precedence.'),

                                                    self.register_cli_opts(self._config_opts)

                                                    self.project = project
                                                    self.prog = prog
                                                    self.version = version
                                                    self.usage = usage
                                                    self.default_config_files = default_config_files

                                        </self._setup>

                                        self._namespace = self._parse_cli_opts(args if args is not None
                                                                                else sys.argv[1:])
                                        # 将解析的配置内容放进_namespace中
                                        <self._namespace function="解析配置文件与命令行参数">
                                            def _parse_cli_opts(self, args):
                                                self._args = args

                                                for opt,group in self._all_cli_opts():
                                                    <self._all_cli_opts path="" function="产生器 输出opt, group">
                                                        def _all_cli_opts(self):
                                                            for ite in self._cli_opts:
                                                                yield item['opt'], item['group']
                                                    </self._all_cli_opts>

                                                    opt._add_to_cli(self._oparser, group)
                                                    <_add_to_cli path="oslo_config.cfg.Opt" name="opt._add_to_cli(self._oparser, group)" function="使选项在命令行中可用">
                                                        def _add_to_cli(self, parser, group=None):

                                                            container = self._get_argparse_container(parser, group)
                                                            <self._get_argparse_container args="(parser, group)" function="">
                                                                def _get_argparse_container(self, parser, group):
                                                                    # 返回argparse._ArgumentGroup 如果group已经给出,否则返回parser
                                                                    # parser: argparse.ArgumentParser
                                                                    # opt: OptGroup 对象

                                                                    if group is not None:

                                                                        return group._get_argparse_group(parser)
                                                                        <group._get_argparse_group values="parser" path="oslo_config.cfg.OptGroup" function="为OptGroup对象构建argparse._ArgumentGroup" >
                                                                            def _get_argparse_group(self, parser):
                                                                                if self._argparse_group is None:

                                                                                    self._argparse_group = parse.add_argument_group(self.title, self.help)
                                                                                    <parse.add_argument_group>
                                                                                        # 这个是argument.ArgumentParser(...).add_argument_group
                                                                                    </parse.add_argument_group>
                                                                                return self._argparse_group





                                                                        </group._get_argparse_group>

                                                            </self._get_argparse_container>

                                                            kwargs = self._get_argparse_kwargs(group)
                                                            <self._get_argparse_kwargs path="oslo_config.cfg.Opt" values="group" function="为add_argument()准备好参数">
                                                                def _get_argparse_kwargs(self, group, **kwargs):
                                                                    # 大多Opt继承并覆写该方法
                                                                    if not self.positional:
                                                                        dest = self.dest
                                                                        if group is not None:
                                                                            dest = group.name + '_' + dest
                                                                        kwargs['dest'] = dest
                                                                    else:
                                                                        kwargs['nargs'] = '?'
                                                                    kwargs.update({'default': None,
                                                                                    'metavar': self.metavar,
                                                                                    'help': self.help})
                                                                    return kwargs


                                                            </self._get_argparse_kwargs>

                                                            prefix = self._get_argparse_prefix('', group.name if group else None)
                                                            <self._get_argparse_prefix values="('', group.name if group else None)" function="">
                                                                def _get_argparse_prefix(self, prefix, group_name):
                                                                    # return: prefix if not group_name else group_name + '-' + prefix

                                                                    if group_name is not None:
                                                                        return group_name + '-' + prefix
                                                                    else:
                                                                        return prefix

                                                            </self._get_argparse_prefix>

                                                            deprecated_names = []
                                                            for opt in self.deprecated_opts:
                                                                # self.deprecated_opts = copy.deepcopy(deprecated_opts) or []

                                                                deprecated_name = self._get_deprecated_cli_name(opt.name,
                                                                                                                opt.group)
                                                                <self._get_deprecated_cli_name function="为淘汰的选项构建CLI参数名">

                                                                    def _get_deprecated_cli_name(self, dname, dgroup, prefix=''):
                                                                        # return self._get_argparse_prefix(prefix, dgroup) + (dname if dname is None else dname)
                                                                        # if dgroup != 'DEFAULT' ...
                                                                        if dgroup == 'DEFAULT':
                                                                            dgroup =None
                                                                        if dname is None and dgroup is None:
                                                                            return None
                                                                        if dname is None:
                                                                           dname = self.name
                                                                        return self._get_argparse_prefix(prefix, dgroup) + dname

                                                                </self._get_deprecated_cli_name>
                                                                if deprecated_name is not None:
                                                                    deprecated_names.append(deprecated_name)

                                                            self._add_to_argparse(parser,container, self.name, self.short,
                                                                                    kwargs, prefix,
                                                                                    self.positional, deprecated_names)
                                                            <self.add_to_argparse values="(parser, container, self.name, self.short, kwargs, prefix)">
                                                               def _add_to_argparse(self, parser, container, name, short, kwargs,
                                                                                    prefix='', positional=False, deprecated_names=None):
                                                                    # 将选项加入argprese parser 或者group
                                                                    # container: argument._ArgumentGroup object
                                                                    # kwargs: key argu for add_argument()
                                                                    # positional: 是否这一选项是positional CLI argument 初始化的时候赋值
                                                                    def hyphen(arg):
                                                                        return arg if not positional else ''
                                                                    args = [hypen('--') + prefix + name]
                                                                    if short:
                                                                        args.append(hyphen('-') + short)
                                                                    for deprecated_name in deprecated_names:
                                                                        args.append(hypen('--') + deprecated_name)
                                                                    parser.add_parser_argument(container, * args, **kwargs)

                                                            </self.add_to_argparse>





                                                    </_add_to_cli>

                                            return self._parse_config_files()
                                            <self._parse_config_files values="" path="oslo_config.cfg.ConfigOpts">
                                                def _parse_config_files(self):
                                                    namespace = _Namespace(self):
                                                    for arg in self._args:
                                                        if arg == '--config-file' or arg.startswith('--config-file=')
                                                            break
                                                    else: # for 遍历未遇到break则进行else操作
                                                        for config_file in self.default_config_files:
                                                            ConfigParser._parse_file(config_file, namespace)

                                                    self._oparser.parse_args(self._args, namespace)
                                                    self._validate_cli_options(namespace)
                                                    return namespace



                                            </self._parse_config_files>

                                        </self._namespace>

                                        if self._namespace._files_not_found: # namespace 类中初始化 self._files_not_found = []
                                            raise ConfigFilesNotFOundError(self._namespace._files_not_found):
                                        if self._namespace._files_premission_denied: #  同样初始化self._files_premission_denied = []
                                            raise ConfigFilesPermissionDeniedError(
                                                    self._namespace._files_premission_denied)

                                        self._check_required_opts()
                                        <self._check_required_opts values="()" path="oslo_config.cfg.ConfigOpts" function="">
                                            def _check_required_opts(self, namespace=None):
                                                # 检测是否所以标记为required的opts是否用值指定

                                                for info, group in self._all_opt_infos():
                                                    # self._all_opt_info() 产生器,无group 与有group
                                                    <self._all_opt_info>
                                                        def _all_opt_info(self):
                                                            for info in self._opts.values():
                                                                yield info, None
                                                            for group in self._groups.values():
                                                                for info in group._opts.values():
                                                                    yield info, group


                                                    </self._all_opt_info>
                                                    opt = info['opt']
                                                    if opt.required:
                                                        if 'default' in info or 'override' in info:
                                                            continue

                                                        if self._get(opt.dest, group, namespace) is None:
                                                        <self._get path="oslo_config.cfg.ConfigOpts" name="self._get(opt.dest, group, namespace) is None" function="取值">
                                                            def _get(self, name, group=None, namespace=None):
                                                                if isinstance(group, OptGroup): # 如果是OptGroup类
                                                                    key = (group.name, name)
                                                                else:
                                                                    key = (group, name)
                                                                try:
                                                                    if namespace is not None:
                                                                        raise KeyError:
                                                                    return self._cache[key]
                                                                except KeyError:

                                                                    value = self._do_get(name, group, namespace)
                                                                    <self._do_get name="self._do_get(name, group, namespace)" function="取值">
                                                                        # 取opt对象的值
                                                                        # return: 选项值或者 GroupAtt对象
                                                                        def _do_get(self, name, group=None, namespace=None):
                                                                            if group is None and name in self._groups:
                                                                                return self.GroupAttr(self, self._get_group(name))
                                                                            info = self._get_opt_info(name, group)
                                                                            opt = info('opt')
                                                                            if isinstance(opt, SubCOmmandOpt):
                                                                                return self.SubCOmmandAttr(self, group, opt.dest)

                                                                            if 'override' in info:
                                                                                namespace = self._substitute(info['override'])
                                                                                <self._substitute path="oslo_config.cfg.ConfigOpts" name="self._substitute(info['override'])">
                                                                                    def _substitute(self, value, group=None, namespace=None):
                                                                                        #用值替换template变量
                                                                                        if isinstance(value, list):
                                                                                            return [self._substitute(i, group=group, namespace=namespace) for i in value]
                                                                                        elif isinstance(value, str):
                                                                                            # 将 '\$' 替换成'$$'
                                                                                            if '\$' in value:
                                                                                                value = value.replace('\$', '$$')

                                                                                            tmpl = self.Template(value)
                                                                                            <self.Template name="self.Template(value)" path="oslo_config.cfg.ConfigOpts">
                                                                                                设置模板类,规则参数开头
                                                                                                class Template(string.Template):
                                                                                                    idpattern = r'[_a-z][\.a-z0-9]*'

                                                                                            </self.Template>


                                                                                            ret = tmpl.safe_substitute(
                                                                                                    self.StrSubWrapper(self, group=group, namespace=namespace))
                                                                                            <tmpl.safe_substitue path='/usr/lib/../../string.Template' value="self.StrWrapper(self, group=group, namespace=namespace)">
                                                                                                from string import Template
                                                                                                def safe_substitute(*args, **kws): # 不传self,后面其实也是有了
                                                                                                    if not args:
                                                                                                        raise TypeError("descriptor 'safe_substitute' of 'Tempalte' object"
                                                                                                                        "needs an argument")
                                                                                                    self, args = args[0], args[1:]
                                                                                                    if len(args) > 1:
                                                                                                        raise TypeError('Too many positional arguments')
                                                                                                    if not args:
                                                                                                        mappings = kws
                                                                                                    elif kws:

                                                                                                        mapping = _multimap(kws, args[0])
                                                                                                        <_multimap values="(kws, args[0])" functions="将参数装到这个类里面,复写get">
                                                                                                            class _multimap:
                                                                                                                def __init__(self, primary, secondary):
                                                                                                                    self._primary = primary
                                                                                                                    self._secondary = secondary
                                                                                                                def __getitem__(self, key):
                                                                                                                    try:
                                                                                                                        return self._primary[key]
                                                                                                                    except KeyError:
                                                                                                                        return self._secondary[key]

                                                                                                        </_multimap>
                                                                                                        else:
                                                                                                            mapping = args[0]
                                                                                                        def convert(mo):
                                                                                                            # 辅助.sub()
                                                                                                            named = mo.group('named') or mo.group('braced')
                                                                                                            if named is not None:
                                                                                                                try:
                                                                                                                    return '%s' % (mapping[named],)
                                                                                                                except KeyError:
                                                                                                                    return mo.group()
                                                                                                            if mo.group('escaped') is not None:
                                                                                                                return self.delimiter
                                                                                                            if mo.group('invalid') is not None:
                                                                                                                return mo.group()
                                                                                                            raise ValueError('Unrecognized named group in pattern',
                                                                                                                            self.pattern)
                                                                                                        # self.pattern 是re... metaclass继承
                                                                                                        return self.pattern.sub(convert, self.template)
                                                                                                        <self.StrSubWrapper path='oslo_config.cfg.ConfigOpts' values="(self, group, namespace=namespace)" path="">
                                                                                                            clas StrSubWrapper(object):
                                                                                                                # 将opt值暴露成字典
                                                                                                                def __init__(self, conf, group=None, namespace=None):
                                                                                                                    # conf: ConfigOpts object
                                                                                                                    self.conf = conf
                                                                                                                    self.namespace = namespace
                                                                                                                    self.group = group
                                                                                                                def __getitem__(self, key):
                                                                                                                    # key: opt name
                                                                                                                    # return: opt value
                                                                                                                    try:
                                                                                                                        group_name, option = key.split('.', 1)
                                                                                                                    except ValueError:
                                                                                                                        group = self.group
                                                                                                                        option = key
                                                                                                                    else:
                                                                                                                        group = OptGroup(name=group_name)
                                                                                                                    try:
                                                                                                                        value = self.conf._get(option, group=group,
                                                                                                                                                namespace=self.namespace)

                                                                                                                    except NoSuchOptError:
                                                                                                                        value = self.conf._get(key, namespace=self.namespace)
                                                                                                                    if isinstance(value, self.conf.GroupAttr):
                                                                                                                        raise TemplateSubstituteError(
                                                                                                                            'substituting group %s not supported' % key)
                                                                                                                    return value

                                                                                                        </self.StrSubWrapper>


                                                                                            </tmpl.safe_substitue>
                                                                                            return ret
                                                                                        else:
                                                                                            return value




                                                                                </self._substitute>


                                                                    </self._do_get>

                                                                    self.__cache[key] = value


                                                        </self._get>
                                                            raise RequiredOptError(opt.name, group)



                                        </self._check_required_opts>
                                </CONF>

                                pre_setup_logging_fn()
                                <pre_setup_logging_fn name="()" path="keystone.server.eventlet" function="eventlet thread">

                                    pre_setup_logging_fn=configure_threading

                                    def configure_threading():
                                        monkeypatch_thread = not CONF.standard_threads
                                        # CONF.standard_threads 在path: keystone.common.config.configure中有 default=False

                                        pydev_debug_url = utils.setup_remote_pydev_debug()
                                        <utils.setup_remote_pydev_debug value="()" path="keystone.common.utils" function="使用pydev调试的才有用">
                                            # 使用pydev调试的才有用
                                            def setup_remote_pydev_debug():
                                                if CONF.pydev_debug_host and CONF.pydev_debug_port: # 没有默认值
                                                    try:
                                                        try:
                                                            from pydev import pydevd
                                                        except ImportError:
                                                            import pydevd
                                                        pydevd.settrace(CONF.pydev_debug_host,
                                                                    port=CONF.pydev_debug_port,
                                                                    stdoutToServer=True,
                                                                    stderrToServer=True)
                                                        return True
                                                    except Exception:
                                                        LOG.exception(_LE('Error...'))

                                                        raise

                                        </utils.setup_remote_pydev_debug>
                                        if pydev_debug_url: # CONF.standard_threads = False
                                            monkeypatch_thread = False

                                        from keystone.common import environment
                                        environment.use_eventlet(monkeypatch_thread)
                                        <environment.use_eventlet values="(monkeypatch_thread)" path="keystone.common.environment.__init__">

                                            monkeypathc_thread = True

                                            @configure_once(eventlet')
                                            <configure_once values="eventlet" function="" path=".">
                                                def configure_once(name):
                                                    # 确保环境配置只执行一次
                                                    _configured = False
                                                from oslo_config import log

                                                LOG = log.getLogger(__name__)
                                                <log.getLogger values="(__name__)" path="oslo_log.log">
                                                    def getLogger(name=None, project='unknown', version='unknown'):
                                                        if name not in _loggers: # _loggers = {}
                                                            _loggers[name] = KeywordArgumentAdapter(logging.getLogger(name),
                                                                                                    {'project': project,
                                                                                                    'version': version})
                                                            <KeywordArgumentAdapter values="(logging.getLogger(name), {'project': project, 'version': version})" path="'.'">



                                                            </KeywordArgumentAdapter>

                                                        return _loggers[name]
                                                </log.getLogger>

                                                    def decorator(func):
                                                        @functools.wrap(func)
                                                        def wrapper(*args, **kwargs):
                                                            global _configured
                                                            if _configured:
                                                                if _configured == name:
                                                                    return
                                                                else:
                                                                    raise SystemError("Environment has already been"
                                                                                        "configured as %s" % _configured)
                                                            LOG.debug("ENvironment configured as: %s", name)
                                                            _configured = name
                                                            return func(*args, **kwargs)
                                                        return wrapper
                                                    return decorator


                                            </configure_once>
                                            Server = None
                                            httplib = None
                                            subprocess = None
                                            global httplib, subprocess, Server
                                            os.environ['EVENTLET_NO_GREENDNS'] = 'yes'
                                            # 必须在初始import eventlet时设置一下,以防存在dnspython
                                            # 那么socket.getaddinfo()将在IPV6下无法工作
                                            import eventlet
                                            from eventlet.green import httplib as _httplib
                                            from eventlet.green import subprocess as _subprocess

                                            from keystone.common.environment import eventlet_server

                                            if monkeypatch_thread is None:
                                                monkeypatch_thread = not os.getenv('STANDARD_THREADS')

                                            eventlet.wsgi.MAX_HEADER_LINE = 16384
                                            # 默认为8192

                                            eventlet.patcher.monkey_patch(os=False, select=True, socket=True,
                                                                        thread=monkeypatch_thread, time=True,
                                                                        psycopg=False, MySQLdb=False)

                                            <eventlet.patcher.monkey_patch values="on=False...">
                                                def monkey_patch(**on):
                                                    acceptd_args = set(('os','select', 'socket',
                                                                        'thread', 'time', 'psycopg', 'MySQLdb',
                                                                        'buildins'
                                                                        ))
                                                    assert not ('__builein__' in on and 'buildins' in on)
                                                    try:
                                                        b = on.pop('__buildtn__')
                                                    except KeyError:
                                                        pass
                                                    else:
                                                        on['builtins'] = b
                                                    default_on = on.pop('all', None)
                                                    for k in six.iterkeys(on):
                                                        if k not in accepted_args:
                                                            raise TypeError("monkey_patch() got an unexpected"
                                                                            "keyword argument %r" % k)
                                                    if default_on is None:
                                                        default_on = not (True in on.values())
                                                        # default_on = True
                                                    for modname in accepted_args:
                                                        if modname == 'MySQLdb':
                                                            on.setdefault(modname, False)
                                                        if modname == 'builtins':
                                                            on.setdefault(modname, False)
                                                    modules_to_patch = []

                                                    # 下面就是import eventlet的各个库了,先判断后import
                                                    if on['os'] and not already_patched.get('os'): # already_patched = {}
                                                        modules_to_patch += _green_os_modules()
                                                        already_patched['os'] = True
                                                    if on['select'] and not already_patched.get('select'):
                                                         modules_to_patch += _green_select_modules()
                                                        already_patched['select'] = True

                                                    if on['socket'] and not already_patched.get('socket'):
                                                        modules_to_patch += _green_socket_modules()
                                                        <_green_socket_modules path=".">
                                                            from eventlet.green import socket
                                                            try:
                                                                from eventlet.green import ssl
                                                                return [('socket', socket), ('ssl', ssl)]
                                                            except ImportError:
                                                                return [(''socket), socket]
                                                        </_green_socket_modules>
                                                        already_patched['socket'] = True

                                                    if on['thread'] and not already_patched.get('thread'):
                                                        modules_to_patch += _green_thread_modules()
                                                        already_patched['thread'] = True
                                                    if on['time'] and not already_patched.get('time'):
                                                        modules_to_patch += _green_time_modules()
                                                        already_patched['time'] = True
                                                    if on.get('MySQLdb') and not already_patched.get('MySQLdb'):
                                                        modules_to_patch += _green_MySQLdb()
                                                        already_patched['MySQLdb'] = True
                                                    if on.get('builtins') and not already_patched.get('builtins'):
                                                        modules_to_patch += _green_builtins()
                                                        already_patched['builtins'] = True
                                                    if on['psycopg'] and not already_patched.get('psycopg'):
                                                        try:
                                                            from eventlet.support import psycopg2_patcher
                                                            psycopg2_patcher.make_psycopg_green()
                                                            already_patched['psycopg'] = True
                                                        except ImportError:
                                                            pass


                                                    imp.acquire() # import lock
                                                    try:
                                                        for name, mod in modules_to_patch:
                                                            orig_mod = sys.modules.get(name)
                                                            # 获取name模块, 因为在modules_to_patch 中已经该import的import了
                                                            if orig_mod is None:
                                                                orig_mod = __import__(name)
                                                            for attr_name in mod.__patched__:
                                                                # 查看是否已经patched attr_name 覆写的方法

                                                                patched_attr = getattr(mod, attr_name, None)
                                                                #获取覆写的方法
                                                                if patched_attr is not None:
                                                                    setattr(orig_mod, attr_name, patched_attr)
                                                                    # orig_mod.attr_name = patched_attr
                                                    finally:
                                                        imp.release_lock()
                                                    if sys.version_info >= (3, 3)
                                                        import importlib._bootstrap
                                                        thread = original('_thread')
                                                        importlib._bootstrap._thread = thread
                                                        import threading
                                                        threading.RLock = threading.PyRLock









                                            </eventlet.patcher.monkey_patch>

                                            Server = eventlet_server.Server # keystone.common.environment.eventlet_server.Server
                                            <Server name="eventlet_server.Server" path="keystone.common.environment.eventlet_server.Server">

                                                class Server(service.ServiceBase):
                                                    <service.ServiceBase path="oslo_service.ServiceBase">
                                                        @six.add_metaclass(abc.ABCMeta)
                                                        class ServiceBase(object):
                                                            # 任何服务的基础类
                                                            @abc.abstractmethod
                                                            def start(self):
                                                                # 启动服务
                                                            @abc.abstractmethod
                                                            def stop(self):
                                                                # 停止服务
                                                            @abc.abstractmethod
                                                            def wait(self):
                                                                # 等待服务完结
                                                            @abc.abstractmethod
                                                            def reset(self):
                                                                # 重置服务
                                                                # 接受SIGHUP时候

                                                    </service.ServiceBase>
                                                    # Server class 管理多个WSGI sockets以及applications

                                                    def __init__(self, application, host=None, port=None, keepalive=False, keepidle=None):
                                                        self.application = application
                                                        self.host = host or '0.0.0.0'
                                                        self.port = port or 0
                                                        # pool for a green thread wsgi服务将执行此pool
                                                        self.pool = eventlet.GreenPool(POOL_SIZE)
                                                        self.socket_info = {}
                                                        self.greenthread = None
                                                        self.do_ssl = False
                                                        self.cert_required = False
                                                        self.keepalive = keepalive
                                                        self.socket = None
                                                        self.keepidle = keepidle

                                                    def listen(self, key=None, backlog=128):
                                                        # backlog 为排队上限
                                                        # 创建并启动socket监听
                                                        # 在fork worker进程前调用
                                                        # getadd_info不支持ip6
                                                        info = socket.getaddinfo(self.host,
                                                                                self.port,
                                                                                socket.AF_UNSPEC,
                                                                                socket.SOCK_STREAM)[0]
                                                        try:
                                                            self.socket = eventlet.listen(info[-1], family=info[0], backlog=backlog)
                                                        except EnvironmentError:
                                                            LOG.error(_LE("Could not bind to %(host)s: %(port)s"),
                                                                    {'host': self.host, 'port': self.port})
                                                            raise
                                                        LOG.info(_LI('Starting %(arg0)s on %(host)s:%(port)s'),
                                                                {'arg0': sys.argv[0],
                                                                'host': self.host,
                                                                'port': self.port})

                                                    def start(self, key=None, backlog=128):
                                                        # run a wsgi server with 给定的application
                                                        if self.socket is None:
                                                            self.listen(key=key, backlog=backlog)

                                                        dup_socket = self.socket.dup()
                                                        <self.socket.dup path="eventlet.greenio.base.GreenSocket">
                                                            #就是将socket重新初始化成_socketobject(), 设置非阻塞
                                                        </self.socket.dup>
                                                        if key:
                                                            self.socket_info[key] = self.socket.getsocketname()
                                                        # SSL使能
                                                        if self.do_ssl: # 初始化赋值
                                                            if self.cert_required: # 初始化赋值
                                                                cert_reqs = ssl.CERT_REQUIRED # ssl.CERT_REQUIRED = 2 path='ssl'
                                                            else:
                                                                cert_reqs = ssl.CERT_NONE # ssl.CERT_NONE = 0 path='ssl'
                                                            dup_socket = socket.wrap_ssl(dup_socket, certfile=self.certfile,
                                                                                        keyfile=self.keyfile,
                                                                                        server_side=True,
                                                                                        cert_reqs=cert_reqs,
                                                                                        ca_certs=self.ca_certs)
                                                            # 包装成ssl socket
                                                        if self.keepalive:
                                                        # wsgi socket要保活
                                                            dup_socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # 设置配置
                                                            if self.keepidle is not None:
                                                                dup_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, self.keepidle)
                                                            self.greenthread = self.pool.spwan(self._run,
                                                                                                self.application,
                                                                                                dup_socket)

                                                    def set_ssl(self, certfile, keyfile=None, ca_certs=None, cert_required=True):
                                                        self.certfile = certfile
                                                        self.keyfile = keyfile
                                                        self.ca_certs = ca_certs
                                                        self.cert_required = cert_required
                                                        self.do_ssl = True

                                                    def stop(self):
                                                        if slef.greenthread is not None:
                                                            self.greenthread.kill()

                                                    def wait(self):
                                                        try:
                                                            self.pool.waitall()
                                                        except KeyboardInterrupt:
                                                            pass
                                                        except greenlet.GreenletExit:
                                                            pass

                                                    def reset(self):
                                                        pass

                                                    def _run(self, application, socket):
                                                        logger = log.getLogger('eventlet.wsgi.server')
                                                        # [eventlet_server]client_socket_timeout 在keystone.conf中
                                                        # 应该设置为整数,但是为了让eventlet.wsgi.server()永远服务,设置为了0
                                                        socket_timeout = CONF.eventlet_server.client_socket_timeout or None
                                                        try:
                                                            eventlet.wsgi.server(
                                                                socket, application, log=EventletFilteringLogger(logger),
                                                                debug=False, keepalive=CONF.eventlet_server.wsgi_keep_alive,
                                                                socket_timeout=socket_timeout)
                                                        except greenlet.GreenExit:
                                                            # 直至所以的servers 完成运行
                                                        except Exception:
                                                            LOG.exception(_LE('Server error'))
                                                            raise








                                            </Server>


                                            httplib = _httplib # eventlet.green.httplib

                                            subprocess = _subprocess # eventlet.green.subprocess






                                        </environment.use_eventlet>

                                </pre_setup_logging_fn>

                                config.setup_logging()
                                <config.setup_logging path="keystone.config">
                                    from oslo_log import log
                                    import logging
                                    def setup_logging():

                                        log.setup(CONF, 'keystone')
                                        <log.setup values="(CONF, 'keystone')" path="oslo_log.log">
                                            def setup(conf, product_name, version='unknown'):
                                                if conf.log_config_append: # None
                                                    _load_log_config(conf.log_config_append)
                                                else:

                                                    _setup_logging_from_conf(conf, product_name, version)
                                                <---------------------------------这个以后在分析>
                                                sys.excepthook = _create_logging_excepthook(product_name)

                                        </log.setup>
                                        logging.captureWarnings(True)
                                        # 如果设为True,重定向所以的warning到 logging package
                                </config.setup_logging>
                            </common.configure>

                        paste_config = config.find_paste_config()
                        <config.find_paste_config name="paste_config = config.find_paste_config()" path="keystone.config">
                            # 寻找keystone paste.deploy 配置文件
                            # 配置文件路径已经在keystone.conf 中的[paste_desploy]设置出来了
                            if CONF.paste_deploy.config_file:
                                paste_config = CONF.paste_deploy.config_file
                                paste_config_value = paste_config
                                if not os.path.isabs(paste_config):

                                    paste_config = CONF.find_file(paste_config)
                                    <CONF.find_file values="paste_config" path="oslo_config.cfg.ConfigOpts" function="定位配置文件的绝对路径">
                                    def find_file(self, name):
                                        dirs = []
                                        if self.config_dir:
                                            dirs.append(_fixpath(self.config_dir))

                                        for cfg in reversed(self.config_file):
                                            dirs.append(os.path.dirname(_fixpath(cf)))
                                        dirs.extend(_get_config_dirs(self.project))

                                        return _search_dirs(dirs, name)
                                        <_search_dirs values="(dir, name)" path=".">
                                            def _search_dirs(dirs, basename, extension=""):
                                                for d in dirs:
                                                    path = os.path.join(d, '%s%s' % (baename, extension))
                                                if os.path.exists(path):
                                                    return path

                                        </_search_dirs>


                                    </CONF.find_file>

                                elif CONF.config_file:
                                    paste_config = CONF.config_file[0]
                                    paste_config_value = paste_config
                                else:
                                    paste_config = CONF.find_file('keystone.conf')
                                    paste_config_value = 'keystone.conf'
                                if not paste_config or not os.path.exists(paste_config):
                                    raise exception.ConfigFileNotFound(config_file=paste_config_value)
                                return paste_config






                        </config.find_paste_config>
                    _unused, servers = common.setup_backends(
                                        startup_application_fn=create_servers)
                    <common.setup_backends values="startup_application_fn=creste_servers" path="keystone.server.common">
                        def setup_backs(load_extra_backends_fn=lambda: {},
                                        startup_application_fn=lambda: None):
                            # start_application_fn = create_servers

                            drivers = backends.load_backends()
                            <backends.load_backends values="" path="keystone.common.backends">
                                from keystone import assignment
                                from keystone import auth
                                from keystone import catalog
                                from keystone.common import cache
                                from keystone.contrib import endpoint_filter
                                from keystone.contrib import fedration
                                from keystone.contrib import oauth1
                                from keystone.contrib import revoke
                                from keystone import credential
                                from keystone import endpoint_policy
                                from keystone import identity
                                from keystone import policy
                                from keystone import resource
                                from keystone import token
                                from keystone import trust
                                def load_backends():
                                    # 配置并且创建cache

                                    cache.configure_cache_region(cache.REGION)
                                    <cache.configure_cache_region values="cache.REGION" path="keystone.common.cache.core">
                                        cache.REGION
                                        <cache.REGION path="keyston.common.cache.core">
                                            REGION = dogpile.cache.make_region(
                                                    function_key_generator=function_key_generator)
                                            # 返回的REGION是cache的前端,可以通过其进行存取
                                            # 但还需要配置一番,具体的可以再研究研究

                                        </cache.REGION>

                                        def configure_cache_region(region):
                                            # 配置 cache region
                                            # return: CacheRegion
                                            if not isinstance(region, dogpile.cache.CacheRegion):
                                                raise exception.ValidationError(
                                                    _('region not type dogpile.cache.CacheRegion'))

                                            if not region.is_configured:
                                                <is_configured path="dogpile.cache.region.CacheRegion">
                                                    @property
                                                    def is_configured(self):
                                                        return 'backend' in self.__dict__
                                                </is_configured>

                                                config_dict = build_cache_config()
                                                <build_cache_config path=".">
                                                    # 创建配置文件字典
                                                    # return: conf_dict
                                                def build_cache_conf():
                                                    prefix = CONF.cache.config_prefix
                                                    # 在keystone.common.config 还是keystone.conf都有设置
                                                    # CONF.cache.config_prefix = cache.keystone
                                                    conf_dict = {}
                                                    conf_dict['%s.backend' % prefix] = CONF.cache.backend
                                                    conf_dict['%s.expiration_time' % prefix] = CONF.cache.expiration_time
                                                    for argument in CONF.cache.backend_argument:
                                                        try:
                                                            argument, argvalue = argument.split(':', 1)
                                                        except ValueError:
                                                            msg = _LE('Unable to build cache config-key. Expected format'
                                                                       '"argname: value" . Skipping unknown format: %s' )
                                                            LOG.error(msg, argument)
                                                            continue
                                                        arg_key = '.'.join([prefix, 'arguments', argname])
                                                        conf_dict[arg_key] = argvalue
                                                    conf_dict.setdefault('%s.argument.url' % prefix,
                                                                        CONF.cache.memcache_servers)
                                                    for arg in  ('dead_retry', 'socket_timeout', 'pool_maxsize',
                                                                'pool_unused_timeout', 'pool_connection_get_timeout'):
                                                        value = getattr(CONF.cache, 'memcache_', arg)
                                                        conf_dict['%s.argument.%s' % (prefix, arg)] = value
                                                    return conf_dict




                                                </build_cache_config>
                                                region.configure_from_config(config_dict,
                                                                            '%s.' % CONF.cache.config_prefix)
                                                # 从配置字典中写入配置
                                                if CONF.cache.debug_backend:
                                                    region.wrap(DebugProxy)
                                                # 下面不是太懂,先这样吧,无关大雅
                                                if region.key_mangler is None:
                                                    region.key_manager = util.sha1_mangle_key
                                                for class_path in CONF.cache.proxies:
                                                    cls = importutils.import_class(class_path)
                                                    LOG.debug("Adding cache-proxy '%s' to backend," class_path)
                                                    region.wrap(cls)
                                            return region




                                    </cache.configure_cache_region>
                                    # 上述不返回值,但是cache.REGION已经设置好了,可以使用cache
                                    # 还有这个参数   on_arguments = REGION.cache_on_arguments

                                    _IDENTITY_API = identity.Manager()
                                    <identity.Manager path="keystone.identity.core">

                                        @notification.listener
                                        <notification.listener path="keystone.notification">
                                            def listener(cls):
                                                # 申明一个类为notification listener
                                                # 一个notification listener必须指定event, 定义event_callbacks
                                                def init_wrapper(init):
                                                    @functools.wraps(init)
                                                    def __new_init__(self, *args, **kwargs):
                                                        init(self, * args, **kwargs)
                                                        _register_event_callbacks(self)
                                                    return __new_init__
                                                def _register_event_callbacks(self):
                                                    for event, resource_types in self.event_callbacks.items():
                                                        for resource_type, callbacks in resource_type.items():

                                                            register_event_callback(event, resource_type, callbacks)
                                                            # 用identity.manager实例
                                                            # register_event_callback('delete', 'domain', self._domain_deleted)

                                                            <register_event_callback values="(event, resource_type, callbacks)">
                                                                def register_event_callback(event, resource_type, callbacks):
                                                                    # register each callback with event
                                                                    # event: 处理事件 类型: keystone.notifications.ACTIONS
                                                                    # resource: 将要被操作的资源类型 参数类型: str
                                                                    # callbacks: 将要与事件进行关联的处理函数
                                                                    if event not in ACTIONS:
                                                                        raise ValueError(_('%(event)s is not a valid notification event, must '
                                                                                         'be one of: %(actions)s') %
                                                                                        {'event': event, 'actions': ', '.join(ACTIONS)})

                                                                    if not hasattr(callbacks, '__iter__'):
                                                                        callbacks = [callbacks]

                                                                    for callback in callbacks:
                                                                        if not callable(callback):
                                                                            # 其实调用就是可以加上() 函数加上可以,类加上也可以
                                                                            # 所以 你懂的 ,只要实现__call__就可以
                                                                            msg = _('Method not callable: %s' % callable)
                                                                            LOG.error(msg)
                                                                        # _SUBSCRIBERS = {}
                                                                        _SUBSCRIBERS.setdefault(event, {}).setdefault(resource_type, set())
                                                                        # 实现结果类似于 {event: {resource_type: set()}}
                                                                        _SUBSCRIBERS[event][resource_type].add(callback)


                                                                        if LOG.logger.getEffectiveLevel() <= logging.DEBUG:
                                                                            msg = 'Callback: `%(callback)s` subscribed to event `%(event)s`.'
                                                                            callback_info = _get_callback_info(callback)
                                                                            callback_str = '.'.join(for i in callback_info if i is not None)
                                                                            event_str = '.'.join(['identity', resource_type, event])
                                                                            LOG.debug(msg, {'callback': callback_str, 'event': event_str})
                                                                            # oslo_log 这一块有时间可以看看










                                                            </register_event_callback>

                                                cls.__init__ = init_wrapper(cls.__init__)
                                                return cls


                                        </notification.listener>

                                        @dependency.provider('identity_api')
                                        <dependency.provider values="(identity_api)" path="keystone.common.dependency">
                                            def provider(name):
                                                # used to register providers
                                                def wrapper(cls):
                                                    def wrapped(init):
                                                        def __wrapped_init__(self, *args, **kwargs):
                                                            # 初始化包裹对象并将其添加到register
                                                            init(self, *args, **kwargs)

                                                            _set_provider(name, self)
                                                            # _REGISTRY[name] = (provider, traceback.format_stack())
                                                            <_set_provider values="(name, self)" path=".">
                                                                # 将self注册进_REGISTRY
                                                                def _set_provider(name, provider):
                                                                    _original_provider, where_registered = _REGISTRY.get(name, (None, None))
                                                                    if where_registered:
                                                                        raise Exception('%s already has a registered provider, at\n%s' %
                                                                                        (name, ''.join(where_registered))

                                                                    _REGISTRY[name] = (provider, traceback.format_stack())
                                                                    # _REGISTRY = {} 初始值
                                                                    # traceback.format_stack()追踪异常的,这个有空再了解


                                                            </_set_provider>

                                                            resolve_future_dependencies(__provider_name=name)
                                                            <resolve_future_dependencies values="(__provider_name=name)" path=".">
                                                                def resolve_future_dependencies(__provider_name=None):
                                                                    # 注入所有依赖
                                                                    # _future_dependencies = {}
                                                                    new_providers = dict()
                                                                    if __provider_name:
                                                                        targets = _future_dependencies.pop(__provider_name, [])
                                                                        for target in targets:

                                                                            setattr(target, __provider_name, get_provider(__provider_name))
                                                                            <get_provider values="(__provider_name)" path=".">
                                                                                def get_provider(name, optional=GET_REQUIRED):
                                                                                    # GET_REQUIRED = object()
                                                                                    if optional is GET_REQUIRED:
                                                                                        return _REQUIRED:
                                                                                    return _REGISTRY.get(name, (None, None))[0]
                                                                            </get_provider>
                                                                        return  # self.keystone = ...





                                                            </resolve_future_dependencies>
                                                        return __wrap_init__
                                                    cls.__init__ = wrapped(cls.__init__)
                                                    _factories[name] = cls # 初始为{}
                                                    return cls
                                                return wrapper



                                        </dependency.provider>

                                        @dependency.requires('assignment_api', 'credential_api', 'id_mapping_api',
                                                                'resource_api', 'revoke_api')
                                        <dependency.requires values="(assignment,..)" path="." function="">
                                            def requires(*dependencies):
                                                def wrapper(self, *args, **kwargs):
                                                    self.__wrapped_init__(*args, **kwargs)

                                                    _process_dependencies(self)
                                                    <_process_dependencies values="self">

                                                    </_process_dependencies>

                                                def wrapped(cls):
                                                    existing_dependencies = getattr(cls, '_dependencies', set())
                                                    cls._dependencies = existing_dependencies.union(dependencies)
                                                    if not hasattr(cls, '__wrapped_init__'):
                                                        cls.__wrapped_init__ = cls.__init__
                                                        cls.__init__ = wrapper
                                                    return cls
                                                return wrapped


                                        </dependency.requires>
                                        class Manager(manager.Manager):
                                            # Identity backend
                                            # 等下我们分析 keystone.common.manager.Manager
                                 driver_namespace = 'keystone.identity'
                                            # 其实这也是entry_point ,manager.Manger初始化时候会用到
                                            _USER = 'user'
                                            _GROUP = 'group'
                                            def __init__(self):

                                                super(Manager, self).__init__(CONF.identity.driver)
                                                <__init__ values="CONF.identity.driver" path="keystone.common.manager.Manager">
                                                    class Manager(object):
                                                        driver_namespace = None
                                                        def __init__(self, driver_name):

                                                            self.driver = load_driver(self.driver_namespace, driver_name)
                                                            # 具体看书签里面的python/entry_point
                                                            # 通过查找egg.info 中的entry_point.txt中的namespace对应选项,获取加载模块
                                                            <load_driver values="(self.driver_namespace, driver_name)" path="keystone.identity.backend.sql.Identity">
                                                                class Identity(identity.Driver):
                                                                    # 覆写__init__方法,使其能够传递config属性,使得sql能够当做domain-specific驱动来使用
                                                                    def __init__(self, conf=None):
                                                                        super(Identity, self).__init__()
                                                                    def default_assginment_driver(self):
                                                                        return 'sql'
                                                                    @property
                                                                    # 将其变成属性调用
                                                                    def is_sql(self):
                                                                        return True
                                                                    def _check_password(self, password, user_ref):
                                                                        return utils.check_password(password, user_ref.password)

                                                                    # 认证接口
                                                                    def authenticate(self, user_id, password):

                                                                        session = sql.get_session()
                                                                        <sql.get_session values="" path="">
                                                                            这个最后再分析

                                                                        </sql.get_session>

                                                                        user_ref = None
                                                                        try:
                                                                            user_ref = self._get_user(session, user_id)
                                                                            <self._get_user values="(session, user_id)" path=".">
                                                                                见下面分析
                                                                            </self._get_user>
                                                                        except exception.UserNotFound:
                                                                            raise AssertionError(_('Invalid user / password'))
                                                                        if not self._check_password(password, user_ref):
                                                                            # 上面已分析
                                                                            raise AssertionError(_('Invalid user / password'))

                                                                        return identity.filter_user(user_ref.to_dict())
                                                                        <user_ref.to_dict values="()" path="keystone.identity.backend.sql.User">
                                                                            def to_dict(self, include_extra_dict=False):
                                                                                # 将self的属性都放入参数中,对于default_project_id 存在并为None则删除
                                                                                d = super(User, self).to_dict(include_extra_dict=include_extra_dict)
                                                                                if 'default_project_id' in d and d['default_project_id'] is None:
                                                                                    del d['default_project_id']
                                                                                return d


                                                                        </user_ref.to_dict>

                                                                        <identity.filter_user values="(user_ref.to_dict)" path="keystone.identity.core">
                                                                            def filter_user(user_ref):
                                                                                # 从user字典中过滤出私密项
                                                                                # 'password' 'tenants' 'group'不会返回
                                                                                # 返回 user_ref
                                                                                if user_ref:
                                                                                    user_ref = user_ref.copy() # 为何要如此做个copy --》
                                                                                    # 这个可以限定在此函数中使用与修改,而不会对整体发生改变
                                                                                    user_ref.pop('password', None)
                                                                                    user_ref.pop('tenants', None)
                                                                                    user_ref.pop('groups', None)
                                                                                    user_ref.pop('domains', None)
                                                                                    try:
                                                                                        user_ref['extra'].pop('password', None)
                                                                                        user_ref['extra'].pop('tenants', None)
                                                                                    except KeyError:
                                                                                        pass
                                                                                return user_ref





                                                                        </identity.filter_user>
                                                                        @sql.handle_conflicts(conflict_type='user')
                                                                        # 在操作数据库遇到问题时候会报错,资源访问不可用报409
                                                                        <sql.handler_conflicts values="(conflict_type='user')" path="keystone.common.sql.core">
                                                                            def handle_conflicts(conflict_type='object'):
                                                                                _conflict_msg = 'Conflict %(conflict_type)s: %(details)s'
                                                                                def decorator(method):
                                                                                    @functools.wraps(method)
                                                                                    def wrapper(*args, **kwargs):
                                                                                        try:
                                                                                            return method(*args, **kwargs)
                                                                                        except db_exception.DEDuplicateEntry as e:
                                                                                            LOG.debug(_conflict_msg, {'conflict_type': conflict_type,
                                                                                                                        'details': six.text_type(e)})
                                                                                            raise exception.Conflict(type=conflict_type,
                                                                                                                    details=_('Duplicate Entry'))
                                                                                        except db_exception.DBError as e:
                                                                                            if isinstance(e.inner_exception, InterityError):
                                                                                                raise exception.UnexceptedError(
                                                                                                    _('An unexpected error occurred when trying to '
                                                                                                        'store %s' ) % conflict_type)
                                                                                        raise


                                                                        </sql.handler_conflicts>
                                                                        def create_user(self, user_id, user)
                                                                            user = utils.hash_user_password(user)
                                                                            # 只将password 哈希化 返回 dict(user, password=hash_password(password))
                                                                            <utils.hash_user_password values="user" path="keystone.common.utils">
                                                                                def hash_user_password(user):

                                                                                    password = user.get('password')
                                                                                    if password is None:
                                                                                        return
                                                                                    return dict(user, password=hash_password(password))


                                                                            </utils.hash_user_password>

                                                                            session = sql.get_session() # 取得sql连接
                                                                            with session.begin():
                                                                                user_ref = User.from_dict(user)
                                                                                # 创建User实例
                                                                                session.add(user_ref)
                                                                            return identity.filter(user_ref.to_dict())









                                                            </load_driver>
                                                        def __getattr__(self, name):
                                                            # self.keystone--->return self.driver 用名字返回驱动实例
                                                            f = getattr(self.driver, name)

                                                            setattr(self, name, f)
                                                            return f



                                                </__init__>
                                                self.domain_configs = DomainConfigs()
                                                <DomainConfigs values="" path=".">
                                                    @dependncy.requires('domain_config_api')
                                                    class DomainConfigs(dict):
                                                        # 这边先分析到此处 ‘domain_config_api以后应该会看到’
                                                </DomainConfigs>

                                                self.event_callbacks = {
                                                    notifications.ACTIONS.deleted: {
                                                        'domain': [self._domain_detleted],
                                                    },
                                                }







                                    </identity.Manager>
                                    _ASSIGNMENT_API = assignment.Manager()
                                    <assignment.Manager values="" path="keystone.assignment.core">
                                        @dependency.provider('assignment_api')
                                        @dependency.requires('credential_api', 'identity_api', 'resource_api',
                                                                'revoke_api', 'role_api')
                                        class Manager(manager.Manager):
                                            driver_namespace = 'keystone.assignment'
                                            _PROJECT = 'project'
                                            _ROLE_REMOVE_FROM_USER = 'role_remove_from_user'
                                            _INVALIDATE_USER_PROJECT_TOKENS = 'invalidate_user_project_tokens'
                                            def __init__(self):
                                                # 如果没有指定驱动的化,我们就让identity告诉我们用什么,为以后identity涵盖
                                                # identity、resource、assignment作准备
                                                assignment_driver = CONF.assignment.driver
                                                if assignment is None:
                                                    identity_driver = dependency.get_provider('identity_api').driver

                                                    assignment_driver = identity_driver.default_assignment_driver()
                                                    <identity_driver.default_assignment_driver path="">
                                                        返回的是一个字符串 'sql' 或者 'ldap'
                                                        现在返回的是'sq'

                                                    </identity_driver.default_assignment_driver>

                                                super(Manager, self).__init__(assignment_driver)
                                                <__init__ values="sql">

                                                </__init__>



                                    </assignment.Manager>

                                    # 确保identity 驱动在assignment manager之前创建
                                    # assignment 驱动在 resource manager之前创建
                                    # 默认resource 驱动依赖assignment,这也导致其依赖于identity,所以需要确保这条链可用
                                    # require 是从_REGISTRY 取出注册的,provider是向_REGISTRY中写入

                                    DRIVERS = dict(
                                        assignment_api=_ASSIGNMENT_API,
                                        catalog_api=catalog.Manager(),  # 'catalog_api'
                                        credential_api=credential.Manager(),    # 'credential_api'
                                        domain_config_api=resource.DomainConfigManager(), # 'domain_config_api'
                                        endpoint_filter_api=endpoint_filter.Manager(), # endpoint_filter_api
                                        endpoint_policy_api=endpoint_policy.Manager(), # endpoint_policy
                                        federation_api=federation.Manager(), # federation_api
                                        id_generator_api=identity.generator.Manager(), # id_generator_api

                                        id_mapping_api=identity.MappingManager(),
                                        identity_api=_IDENTITY_API,
                                        oauth_api=oauth1.Manager(),
                                        policy_api=policy.Manager(),
                                        resource_api=resource.Manager(),

                                        revoke_api=revoke.Manager(), # 添加listener
                                        <revoke.Manager values="" path="keystone.contrib.revoke.core">
                                            @dependency.provider('revoke_api')
                                            class Manager(manager.Manager):
                                                driver_namespace = 'keystone.revoke'
                                                def __init__(self):
                                                    super(Manager, slef).__init__(CONF.revoke.driver)

                                                    self._register_listeners()
                                                    <_register_listeners values="" path="keystone.contrib.revoke.core">
                                                        # 安装listener
                                                        def _register_listeners(self):



                                                    </_register_listeners>
                                                    self.model = model



                                        </revoke.Manager>
                                        role_api=assignment.RoleManager(),
                                        token_api=token.persistence.Manager(),
                                        trust_api=trust.Manager(),
                                        token_provider_api=token.provider.Manager()) # 添加listener

                                    auth.controllers.load_auth_methods()
                                    <auth.controllers.load_auth_methods values="" path="keystone.auth.controllers">
                                        def load_auth_methods():
                                            global AUTH_PLUGIN_LOADED
                                            # AUTH_PLUGIN_LOADED = False
                                            if AUTH_PLUGIN_LOADED:
                                                return
                                            config.setup_authentication() # 将配置那些认证方法注册一遍
                                            for plugin in set(CONF.auth.methods):

                                                AUTH_METHODS[plugin] = load_auth_method(plugin)
                                                # 将其装入AUTH_METHODS字典
                                                <load_auth_method values="plugin" path="">
                                                    def load_auth_method(method):
                                                        plugin_name = CONF.auth.get(method) or 'default'
                                                        try:
                                                            namespace = 'keystone.auth.%s' % method
                                                            driver_manager = stevedore.DriverManager(namespace, plugin_name,
                                                                                                    invoke_on_load=True)
                                                            return driver_manager.driver
                                                        except RuntimeError:
                                                            LOG.debug('Failed to load the %s driver (%s) using stevedore, will '
                                                                'attempt to load using import_object instead.',
                                                                    method, plugin_name)
                                                        @versionutilt.deprecated(as_of=versionutils.deprecated.LIBERTY,
                                                                                in_favor_of='entrypoints',
                                                                                         what='direct import of driver')
                                                        def _load_using_import(plugin_name):
                                                            return importutils.import_object(plugin_name)

                                                </load_auth_method>

                                            AUTH_PLUGINS_LOADED = True





                                    </auth.controllers.load_auth_methods>
                                    return DRIVERS







                            </backends.load_backends>
                            # Router URL的匹配是按照注册顺序进行的
                            # environ['wsgiorg.routing_args'] = ((url, match))
                            # environ['routes.route'] = route
                            # environ['routes.url'] = url
                            drivers.update(load_extra_backends_fn())

                            res = startup_application_fn()
                            <create_servers values="" path="keystone.server.eventlet">

                            </create_servers>
                            dirvers.update(dependency.resolve_future_dependencies())
                            return drivers, res
                    </common.setup_backends>
                    serve(*servers)

                </eventlet_server.run>





    </possible_topdir>



</keystone>

查看原文:http://www.zoues.com/index.php/2015/09/13/keystone-all/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值