我的 OpenStack 代码贡献初体验

OpenStack如今已成为开源云平台中的明星项目,得到广泛关注。OpenStack的优秀出众依赖于众多开发者的努力,在享受其带来的便利与快捷的同时,为其做一份贡献也是一个开发者的义务。在前段时间的OpenStack的测试过程中,我发现Nova项目中的一个Bug,于是向社区提交了Bug报告,并提交代码修复了该Bug,从提交报告到代码入库经历近一月,下面重现整个过程。

一.发现Bug:

Nova中的虚拟机软删除(soft-delete)功能,是指在一段时间内,仅将数据库中的某虚拟机记录做一个标记 (status='SOFT-DELETE'),然后将虚拟化平台(kvm等)中对应的虚拟机实例置为关机状态,当超过某一时间段后才将虚拟机实例真正删除;该功能为云平台用户提供了“后悔时间”,可以在一定程度上挽回误操作。默认情况下,软删除功能是关闭的,其开启方式是在nova配置文件中添加"reclaim_instance_interval"选项,并将其值设置为"后悔时间"的毫秒数。

在描述具体Bug前,需要对openstack中的用户管理方面的基本概念简单介绍一下。

上图是openstack用户模型的简化版本,为了便于理解将不属于keystone管理的quota也拿了过来。

Bug就与软删除相关。具体场景是这样的:假设OpenStack中有两个项目和两个用户:普通项目A其用户a,管理员项目Admin其用户为 admin(用户管理相关概念可以查阅keystone文档),用户a不慎将自己的一台虚拟机删除了,这时求助系统管理员看看有没有办法恢复,好在系统开启的软删除功能,而且被删除的虚拟机还在可回收的时间范围内,这时管理员便以admin的身份登录系统,为用户a恢复了虚拟机,但是细心的管理员却发现了一些不对:其Admin项目下并没有任何虚拟机,但是其配额却被使用了,难道这和刚才的操作有关?再来重试一下:普通用户删除虚拟机,admin用户来为其恢复,这时配额又发生了变化,果然如此:被恢复的虚拟机的配额错误的添加到了Admin项目下。该Bug在最新的kilo版本中仍然存在,感兴趣的同学可以实验一下。

二.定位Bug:

发现了Bug的存在,那就更进一步,到代码中找一下原因吧。

如何确定问题代码的位置呢?这需要对Nova的项目结构有大体的了解,我们来简单了解一下:上图是nova架构的极简版本,与本问题无关的组件都没有画上去,恢复虚拟机的操作过程大致是这样:

  1. nova api接收到用户请求,到数据库中查询虚拟机详情,将该虚拟机所在的主机、名称等数据发送到消息队列中;
  2. nova compute服务在监听到相关消息后,开始执行具体操作,将虚拟机在数据库中的记录做些调整,调用底层驱动恢复虚拟机。

既然软删除的功能层面没有任何问题,虚拟机的删除和恢复过程都很顺利,可见不会是驱动的问题,顺着API层的代码调用往下找,很快就可以定位了。直接看出问题的代码片段:


  1. def restore(self, context, instance): 
  2.     # 该代码做了删减 
  3.     flavor = instance.get_flavor() 
  4.     # 获取quotas对象 
  5.     num_instances, quotas = self._check_num_instances_quota( 
  6.             context, flavor, 1, 1) 
  7.     self._record_action_start(context, instance, instance_actions.RESTORE) 
  8.     try: 
  9.         if instance.host: 
  10.             instance.task_state = task_states.RESTORING 
  11.             instance.deleted_at = None 
  12.             instance.save(expected_task_state=[None]) 
  13.             self.compute_rpcapi.restore_instance(context, instance) 
  14.         else: 
  15.             instance.vm_state = vm_states.ACTIVE 
  16.             instance.task_state = None 
  17.             instance.deleted_at = None 
  18.             instance.save(expected_task_state=[None]) 
  19.         # 更新quotas 
  20.         quotas.commit() 

上面的这段代码就是API层面上进行虚拟机回收的主要方法,可以看到其中有明显的配额操作(quotas),在解读这段代码前有必要先对nova 中"context"的概念做个简介。不仅是nova,在openstack其他项目中都随处可见这个"context",它是一个包装了用户请求信息的对象,包含用户的项目和认证信息等,通过它可以简便的进行各项目之间的API调用和用户信息的查询,API服务接收到用户的每一次HTTP请求,都会创建一个新的context。

回到这段代码,我们重点关注对quotas所作的操作:在方法的第二行,通过了一个方法获取了quotas,有在方法的结尾执行了 quotas.commit(),能够获取到的信息不多,我们再看一下获取quotas的方法:_check_num_instances_quota


  1. # 这里只截取一部分 
  2.  def _check_num_instances_quota(self, context, instance_type, min_count, 
  3.                                 max_count): 
  4.      req_cores = max_count * instance_type['vcpus'] 
  5.      vram_mb = int(instance_type.get('extra_specs', {}).get(VIDEO_RAM, 0)) 
  6.      req_ram = max_count * (instance_type['memory_mb'] + vram_mb) 
  7.  
  8.      try: 
  9.          quotas = objects.Quotas(context) 
  10.          quotas.reserve(context, instances=max_count, 
  11.                         cores=req_cores, ram=req_ram) 
  12.      ... 
  13.      return max_count, quotas 

这里可以看到获取quotas的过程:通过当前的context创建quotas对象,并且执行了reserve操作; 我们知道context是由HTTP请求而来,里面保存的是发请求的用户的信息,所以这里的quotas对象的“所有者”也就是context中的用户。

结合Bug发生的场景来看:管理员还原用户a的虚拟机,发请求的是管理员,当前context中记录的是管理员的信息,这里的quotas理所当然的就是管理员的,然后操作了用户a的虚拟机,更新的却是管理员的quotas。嗯,真相大白!

三.修复Bug:

Bug的原因是获取的quotas并不属于期望的用户,但是直接修改context显然不合适(会影响后续的操作),先了解一下quotas对象自身吧:


  1. class Quotas(base.NovaObject): 
  2.     # 部分代码 
  3.     def __init__(self, *args, **kwargs): 
  4.         super(Quotas, self).__init__(*args, **kwargs) 
  5.         # Set up defaults. 
  6.         self.reservations = [] 
  7.         self.project_id = None 
  8.         self.user_id = None 
  9.         self.obj_reset_changes() 
  10.     ... 
  11.     def reserve(self, context, expire=None, project_id=None, user_id=None, 
  12.                 **deltas): 
  13.         reservations = quota.QUOTAS.reserve(context, expire=expire, 
  14.                                             project_id=project_id, 
  15.                                             user_id=user_id, 
  16.                                             **deltas) 
  17.         self.reservations = reservations 
  18.         self.project_id = project_id 
  19.         self.user_id = user_id 
  20.         self.obj_reset_changes() 
  21.  
  22.     def commit(self, context=None): 
  23.         if not self.reservations: 
  24.             return 
  25.         if context is None: 
  26.             context = self._context 
  27.         quota.QUOTAS.commit(context, self.reservations, 
  28.                             project_id=self.project_id, 
  29.                             user_id=self.user_id) 
  30.         self.reservations = None 
  31.         self.obj_reset_changes() 

注意看reserve方法的参数,默认为None的project_id和user_id,这正是改变quotas属主的方便入口!

修改后的代码这里就不贴了,感兴趣的同学可以到这次提交中看:Code Review

四.代码提交和Review:

openstack社区有着整套项目管理流程,这里有一张图能够较详细的描述工作流程:

由图可见bugfix是其中最简单的流程。

关于如何提交代码,这篇文章有详细的介绍: 向 OpenStack 贡献您的代码。另外需要注意一点,在国内向社区提交代码,经常会因为网络问题导致无法提交,幸好找到了大牛的博客介绍了该类问题的解决办法。  修改完代码的单元测试和pep8本地测试当然不能少,早就知道社区对单元测试要求很严格,这次才真正领教了,三行代码的修改,单元测试却写了30 行,review期间多次因为单元测试的问题重提代码(哭)。社区里面的开发者,尤其是项目的core,对待项目有着像对自己孩子般的认真与细致:他们会在一个自己根本不会在意的地方提醒你、面对当前的问题他们会延伸的考虑类似的问题。他们的态度让我首先感受到的吃惊,然后是敬佩!

经历八次review、历时近一个月,我的代码总算是入库了!希望我的这篇记录能对你有帮助。

感谢休伦公司技术总监 孙琦 提供的英文支持,社区大牛Alex Xu给出的修改建议。

Launchpad上面的bug提交: Abnormal changes of quota usage after instance restored by admin

代码审查过程: Fix abnormal quota usage after restore by admin

Git@OSC中的代码: Fix abnormal quota usage after restore by admin

博文出处:http://my.oschina.net/zyzzy/blog/509315

关于OpenStack

OpenStack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,是一个开源的云计算管理平台项目,由几个主要的组件组合起来完成具体工作。OpenStack支持几乎所有类型的云环境,项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。

OpenStack除了有Rackspace和NASA的大力支持外,还有包括戴尔、Citrix、Cisco、Canonical等重量级公司的贡献和支持,致力于简化云的部署过程并为其带来良好的可扩展性。

本文作者:YueZheng

来源:51CTO

时间: 2024-09-19 08:59:54

我的 OpenStack 代码贡献初体验的相关文章

OpenStack代码贡献初体验

OpenStack如今已成为开源云平台中的明星项目,得到广泛关注.OpenStack的优秀出众依赖于众多开发者的努力,在享受其带来的便利与快捷的同时,为其做一份贡献也是一个开发者的义务.  在前段时间的OpenStack的测试过程中,我发现Nova项目中的一个Bug,于是向社区提交了Bug报告,并提交代码修复了该Bug,从提交报告到代码入库经历近一月,下面重现整个过程. 一.发现Bug:  Nova中的虚拟机软删除(soft-delete)功能,是指在一段时间内,仅将数据库中的某虚拟机记录做一个

Openstack贡献者须知 2 — 社区工作运作 & 代码贡献流程

目录 目录 前文列表 订阅邮件列表 Mailing Lists 社区工作运作流程 Openstack 代码贡献流程 PEP8 Python编程风格 查阅相关资源 前文列表 Openstack贡献者须知 - OpenPGP/SSH/CLA贡献者协议 订阅邮件列表 Mailing Lists 订阅邮件列表之后,你可以在邮件中提出问题并获得帮助.如果你有问题要提出可以直接发送邮件到相关版块的管理员那里去,社区的管理员会非常专业的回答你的问题. 订阅邮件列表:点这里(使用Launchpad Accoun

OpenStack Ocata版本国内代码贡献盘点

2017年2月23日,OpenStack迎来了它的第15个版本--Ocata版本的发布.为了更贴近用户需求,OpenStack基金会将新版本的发布时间从往年的4月份和10月份分别提前到2月份和8月份,而面向用户的OpenStack峰会则在5月份和11月份召开.这一策略调整给了OpenStack厂商更多时间来打磨自己的产品,做到快速升级和保证产品方案的成熟稳定并重,大幅度改善用户体验. 通过分析此次Ocata版本的全球贡献排名,我们欣喜地发现中国企业排名普遍提升,多个厂家贡献排名进入全球Top20

OpenStack Newton发布 EasyStack核心代码贡献中国第一

本周,OpenStack正式发布了第14个版本Newton,使OpenStack成为虚拟化.裸机.容器的统一云平台,并在可扩展性.可靠性和用户体验方面均有显著提升. 同时,Newton全球社区代码贡献排名也新鲜出炉,全球共有181家企业和组织贡献代码.代码贡献是开源社区存在和发展的基础,也是OpenStack企业技术水平和综合实力的表现.中国有23家企业上榜,与上一个版本13家中国企业同比,增长高达77%,成为全球的OpenStack技术的中坚力量. 其中,EasyStack(北京易捷思达科技发

深度解读 OpenStack Liberty 国内代码贡献

又到了 OpenStack 新版本发布的季节,虽然秋意寒寒,但是仍然挡不住 OpenStack 再次掀起全球关注的热点.这是 OpenStack 第12个版本,与之前的沉稳低调相比,这次的 Release 中一口气多了 5 个新模块,也创下了 OpenStack 项目创建以来的最高纪录.由于天然的架构优势,让 OpenStack 在云计算横行天下的年代游刃有余,已经逐步成为了云平台的即成标准,从 OpenStack 对待 AWS 的 API 兼容的态度就能看出,OpenStack 变得越来越自信

Kotlin 初体验:主要特征与应用

Kotlin 是一种针对 Java 平台的新编程语言.它简洁.安全.务实,并且专注于与 Java 代码的互操作性.它几乎可以用在现在Java 使用的任何地方 :服务器端开发.Android 应用,等等.本文我们将详细地探讨 Kotlin 的主要特征. 本文选自<Kotlin实战>. Kotlin初体验 让我们从一个小例子开始,来看看 Kotlin 代码长什么样子.这个例子定义了一个 Person 类来表示"人",创建一个"人"的集合,查找其中年纪最大的人

PostgreSQL 数据库初体验

  10月15日,由山东华鲁科技咨询顾问高强老师在"DBA+济南群"进行了一次关于PostgreSQL数据库初体验的线上主题分享.小编特别整理出其中精华内容,供大家学习交流.   嘉宾简介    高强,"DBA+济南群"联合发起人.现就职于山东华鲁科技发展股份有限公司.擅长Oracle.AIX.Linux.PostgreSQL和DB2等产品的实施.运维和故障处理.曾是一名存储工程师,负责实施存储.双机和备份等产品,在接触到数据库产品后,一发不可收拾的投入了DBA的浩

zephir-(2)安装和初体验

zephir-安装和初体验 前言 先在这里感谢各位zephir开源技术提供者 zephir主要是解决了PHP开发人员尝试编写和编译PHP拓展所能执行的代码的语言.这是一个支持动态/静态类型的语言,熟悉PHP开发人员可以很好的进行开发.zephir这个名字的主要来源是(Zend Engine/PHP/Intermediate),今天首先介绍zephir的安装,接着会对zephir进行一些语法上面的介绍,希望大家喜欢! 注:笔者水平有限,说的不正确的地方希望大家多多指正,一同交流技术 附上: 喵了个

新手RoR十分钟初体验Step By Step

http://yulimin.javaeye.com/blog/35929 关键字: rails   Ruby Rails RoR     新手RoR十分钟初体验Step By Step 声明一下,这是个新手启动的体验文章,高手不要看了...:) 1.安装RubyWindows用户去 http://rubyforge.org/ 的 http://rubyforge.org/projects/rubyinstaller/ 下载 One-Click Installer - Windows 安装即可,