本文地址:http://blog.csdn.net/spch2008/article/details/9700071
这里主要说一下,权限信息的加载过程。
quantum\openstack\common\policy.py中
全局变量_checks = {}是一个字典,存放各种权限验证类。比如;
{'rule':RuleCheck, 'role':RoleCheck},由于使用了装饰器,所以,此模块被加载时,_checks就被初始化了,具体可参见带参数的装饰器。
def register(name, func=None): def decorator(func): _checks[name] = func return func if func: return decorator(func) return decorator @register("role") class RoleCheck(Check): def __call__(self, target, creds): """Check that there is a matching role in the cred dict.""" return self.match.lower() in [x.lower() for x in creds['roles']]由于register只传递一个参数'role',所以,register中func值为None,用返回的decorator函数装饰RoleCheck类,将类存放于_check中。
class Rules(dict): @classmethod def load_json(cls, data, default_rule=None): rules = dict((k, parse_rule(v)) for k, v in jsonutils.loads(data).items()) return cls(rules, default_rule)data为policy.json中的数据,jsonutils.loads将数据组织成字典返回。所以,对于数据
{ "admin_or_owner": [["role:admin"], ["tenant_id:%(tenant_id)s"]], "get_port": [["rule:admin_or_owner"]], }实际返回的就是上述格式的字典,然后进行列表解析。
def parse_rule(rule): if isinstance(rule, basestring): return _parse_text_rule(rule) return _parse_list_rule(rule)rule是一个[["role:admin"], ["tenant_id:%(tenant_id)s"]]存放列表的列表,所以继续调用_parse_list_rule
def _parse_list_rule(rule): #空条目,例如[],返回TrueCheck,永真 if not rule: return TrueCheck() or_list = [] for inner_rule in rule: if isinstance(inner_rule, basestring): inner_rule = [inner_rule] and_list = [_parse_check(r) for r in inner_rule] if len(and_list) == 1: or_list.append(and_list[0]) else: or_list.append(AndCheck(and_list)) # If we have only one check, omit the "or" if len(or_list) == 0: return FalseCheck() elif len(or_list) == 1: return or_list[0] return OrCheck(or_list)得到的and_list如果只有一个,则可以直接加入or_list,如果有多个,需要合成一个AndCheck对象,表示每一个都需要匹配。
最终,如果or_list大于一个元素,则形成一个Orcheck对象。
原理很简单:对于[ ["role:admin"], ["tenant_id:%(tenant_id)s"] ]情况,只需要满足内部一个条件即可, OrCheck。
而对于 ["role:admin", "tenant_id:%(tenant_id)s"] 这种情况,需要每一个都要满足,需要一个AndCheck。
def _parse_check(rule): # Handle the special checks if rule == '!': return FalseCheck() elif rule == '@': return TrueCheck() try: kind, match = rule.split(':', 1) except Exception: return FalseCheck() if kind in _checks: return _checks[kind](kind, match) elif None in _checks: return _checks[None](kind, match) else: return FalseCheck()对于一个规则,rule:admin_or_owner, 拆分成kind(rule)与match(admin_or_owner),如果是'rule','role'等创建相应的对象,
如果没有匹配,则创建一个GenericCheck。