分享

OpenStack建立实例完整过程源码详细分析(7)

xioaxu790 发表于 2014-6-13 09:59:42 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 7928
问题导读:
1、Quota类是如何定义的?





今天,我们继续接着昨天的内容,进行OpenStack建立实例完整过程源码的分析
好了,步如正题了
继续看方法get_project_quotas:
  1. def get_project_quotas(self, context, resources, project_id,
  2. quota_class=None, defaults=True,
  3. usages=True):
  4. """
  5. 根据给定的资源列表,对于给定的对象进行磁盘配额检索;返回磁盘配额;
  6. """
  7. quotas = {}
  8. # 对于一个给定的项目,检索它的所有的磁盘配额;
  9. # 根据project_id查询数据库中相应项目的数据库信息,获取其中的hard_limit值,也就是获取规定的资源最大限额值;
  10. project_quotas = db.quota_get_all_by_project(context, project_id)
  11. # 检索一个给定资源的当前的所有相关的使用情况;
  12. if usages:
  13. project_usages = db.quota_usage_get_all_by_project(context,project_id)
  14. # 通过适当的类获取配额信息。如果project ID匹配context中的一个,那么使用context中的quota_class类,否则,使用所提供的quota_class类(如果有的话)。
  15. # 选取合适的类,为后面做准备;
  16. if project_id == context.project_id:
  17. quota_class = context.quota_class
  18. if quota_class:
  19. class_quotas = db.quota_class_get_all_by_name(context, quota_class)
  20. else:
  21. class_quotas = {}
  22. for resource in resources.values():
  23. # Omit default/quota class values
  24. if not defaults and resource.name not in project_quotas:
  25. continue
  26. quotas[resource.name] = dict(
  27. limit=project_quotas.get(resource.name, class_quotas.get(resource.name, resource.default)),
  28. )
  29. # Include usages if desired. This is optional because one
  30. # internal consumer of this interface wants to access the
  31. # usages directly from inside a transaction.
  32. if usages:
  33. usage = project_usages.get(resource.name, {})
  34. quotas[resource.name].update(
  35. in_use=usage.get('in_use', 0),
  36. reserved=usage.get('reserved', 0),
  37. )
  38. return quotas
复制代码

调用这个方法时传入的参数值:
  1. context = <nova.context.RequestContext object at 0x4e06d90>   
  2. sub_resources = {'instances': <nova.quota.ReservableResource object at 0x2f1e610>, 'ram': <nova.quota.ReservableResource object at 0x2f1e690>, 'cores': <nova.quota.ReservableResource object at 0x2f1e650>}   
  3. project_id = 0e492e86f22e4d19bd523f1e7ca64566   
  4. context.quota_class = None  
复制代码

首先看语句:
  1. project_quotas = db.quota_get_all_by_project(context, project_id)  
复制代码

主要实现了根据指定project_id查询数据库,获取规定的各种资源的限定值,以字典的形式返回给project_quotas。进入方法quota_get_all_by_project:
  1. def quota_get_all_by_project(context, project_id):  
  2.     """
  3.     根据project_id查询数据库中相应项目的数据库信息,获取其中的hard_limit值,也就是获取规定的某一资源最大限额值;
  4.     """  
  5.     nova.context.authorize_project_context(context, project_id)  
  6.   
  7.     rows = model_query(context, models.Quota, read_deleted="no").\  
  8.                    filter_by(project_id=project_id).\  
  9.                    all()  
  10.   
  11.     result = {'project_id': project_id}  
  12.     for row in rows:  
  13.         result[row.resource] = row.hard_limit  
  14.   
  15.     return result  
复制代码

  再看类Quota的定义:
  1. class Quota(BASE, NovaBase):  
  2.     """
  3.     表示针对一个project的配额信息类;
  4.     """  
  5.   
  6.     __tablename__ = 'quotas'  
  7.     id = Column(Integer, primary_key=True)  
  8.   
  9.     project_id = Column(String(255), index=True)  
  10.   
  11.     resource = Column(String(255))  
  12.     hard_limit = Column(Integer, nullable=True)  
复制代码

我们可以知道quota_get_all_by_project返回给project_quotas的结果result是一个字典,它的结果是这种形式:
  1. result = {'project_id': project_id, 'resource1':hard_limit1, 'resource2':hard_limit2,'resource3':hard_limit3, ......}  
  2.   
  3. project_quotas ={'project_id': project_id, 'resource1':hard_limit1, 'resource2':hard_limit2, 'resource3':hard_limit3, ......}  
复制代码

再来看语句:
  1. if usages:  
  2.             project_usages = db.quota_usage_get_all_by_project(context,project_id)  
复制代码
对于usages这个变量,源码中是这样解释的,如果其值设置为True,则当前的in_use和reserved counts也将会被获取并返回;
    来看看方法quota_usage_get_all_by_project:
  1. def quota_usage_get_all_by_project(context, project_id):  
  2.     """
  3.     根据project_id查询数据库,获取各种资源的in_use和reserved配额数据信息;
  4.     """  
  5.     nova.context.authorize_project_context(context, project_id)  
  6.   
  7.     rows = model_query(context, models.QuotaUsage, read_deleted="no").\  
  8.                    filter_by(project_id=project_id).\  
  9.                    all()  
  10.   
  11.     result = {'project_id': project_id}  
  12.     for row in rows:  
  13.         result[row.resource] = dict(in_use=row.in_use, reserved=row.reserved)  
  14.   
  15.     return result  
复制代码


再来看类QuotaUsage的定义:
  1. class QuotaUsage(BASE, NovaBase):  
  2.     """
  3.     表示一个给定资源当前的使用情况;
  4.     """  
  5.   
  6.     __tablename__ = 'quota_usages'  
  7.     id = Column(Integer, primary_key=True)  
  8.   
  9.     project_id = Column(String(255), index=True)  
  10.     resource = Column(String(255))  
  11.   
  12.     in_use = Column(Integer)  
  13.     reserved = Column(Integer)  
  14.     @property  
  15.     def total(self):  
  16.         return self.in_use + self.reserved  
  17.   
  18.     until_refresh = Column(Integer, nullable=True)  
复制代码

我们可以知道quota_usage_get_all_by_project返回给project_usages的结果result是一个字典,它的结果是这种形式:
  1. result = {'project_id': project_id, 'resource1':hard_limit1, 'resource2':hard_limit2, 'resource3':hard_limit3, ......}
复制代码

即:
  1. project_quotas ={'project_id': project_id,  
  2.   
  3.                  'resource1':{'in_use1':in_use1,'reserved1':reserved1},  
  4.   
  5.                  'resource2':{'in_use2':in_use2,'reserved2':reserved2},   
  6.   
  7.                  ......}  
复制代码

再看下面这段代码:
  1. if project_id == context.project_id:  
  2.             quota_class = context.quota_class  
  3.         if quota_class:  
  4.             class_quotas = db.quota_class_get_all_by_name(context, quota_class)  
  5.         else:  
  6.             class_quotas = {}  
复制代码

这里运调试运行了一下,得到了几个变量的值,如下:
    context.quota_class = None
    quota_class = None
    class_quotas = {}
    这说明,没有运行语句:

  1. <span style="font-family:KaiTi_GB2312;font-size:18px;">class_quotas = db.quota_class_get_all_by_name(context, quota_class)</span>
复制代码

   其实这里面的方法quota_class_get_all_by_name和之前分析的两个方法是类似的,只不过之前两个方法都是依据project_id来匹配数据库的,而这里是根据quota_class,而且这里查询的是QuotaClass类,具体为什么会这么设计,目前还没有弄清楚。
    接下来看语句:

  1. for resource in resources.values():  
  2.     # Omit default/quota class values  
  3.     if not defaults and resource.name not in project_quotas:  
  4.         continue  
  5.   
  6.     quotas[resource.name] = dict(  
  7.         limit=project_quotas.get(resource.name, class_quotas.get(resource.name, resource.default)),  
  8.     )  
  9.               
  10.     if usages:  
  11.         usage = project_usages.get(resource.name, {})  
  12.         quotas[resource.name].update(  
  13.             in_use=usage.get('in_use', 0),  
  14.             reserved=usage.get('reserved', 0),  
  15.         )  
复制代码

其实这部分代码完成的是从字典project_quotas和project_usages中,为资源instances、ram和cores读取limit(从project_quotas中)以及in_use和reserved(从project_usages中,根据usages的值判断是否获取)等配额的值;
    因为这个方法传入的usages参数值是False,所以没有获取in_use和reserved配额值;
    所以调试运行了一下,得到如下获取的配额值limit的结果:

  1. resource.name = instances  
  2. limit:10  
  3. resource.name = ram  
  4. limit:51200  
  5. resource.name = cores  
  6. limit:20
复制代码

  方法get_project_quotas的最后,返回从数据库中获取的指定配额信息的值,以字典的形式;
   这个方法完成的就是为project_id指定的对象,从数据库中获取给定的资源列表中指定的资源的配额信息数据,以字典的形式返回。


本文,接上一篇内容:
OpenStack建立实例完整过程源码详细分析(6)

下一篇:
OpenStack建立实例完整过程源码详细分析(8)


没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条