本文介绍如何构建与 OpenStack continuous integration platform贯穿的测试平台。开始前最好对本文upstream OpenStack CI platform in detail中的背景有所了解。读完本文后,你将具备构建测试平台所需的所有背景知识。
测试平台干嘛的?
简单的说,就是 运行第三方的独立测试 — 通过将三方驱动或硬件配置到 OpenStack 环境中 — 然后在代码审查的过程中展示相关的测试报告. 通过这个实时的代码审查回馈能很容易的把控代码质量. 下图中,你会看到Neutron的外部测试平台加入的numberVerified +1 and one Verified -1 标签:
测试平台引入的Verified +1 and -1 标签
每添加一个新的标签就会产生一条comments,点击注释就会链接到测试平台上的相关测试:
Comments 对应着一次测试平台的review
开发人员可以通过访问相应的链接去排查造成测试平台失败的相关补丁问题。
为啥需要外部测试平台?
好处有如下几点:
-
及时获得反馈
-
测试平台能提早发现相关补丁提交后可能造成的失败,这能缩短问题解决时间
-
更好的代码覆盖率
-
通过模拟测试插件和驱动程序来减少对真实测试环境的依赖。以此为开发人员提供更多的时间专注于业务代码的质量
-
持续提高质量标准
-
通过相关用例来测试部分或者全部的驱动程序API以保证与OpenStack的兼容性. 如果你和OpenStack的开发人员聊过,就会知道他们面对如何选择存储或网络供应商或是后台管理模式去兼容将要部署的 OpenStack问题时,这一优势会多么明显!
何必再去思考如何选择测试平台的问题? 已经大把OpenStack项目和供应商探讨过集成测试平台到上游的OpenStack持续集成平台的需求了。Neutron开发社区已经走在前面 ahead of the game,大约快一打的供应商已经在Neutron代码审查中加入了测试的链接.
Cinder项目在讨论 discussions 强制推行一有代码提交就测试驱动的正确性策略。 同样的,Nova 社区也讨论了 discussed 监控源码库的相关策略. 也许这对于有些团队来说不是什么新鲜事, 带希望本文能给新接触 OpenStack的供应商们提供更快融入的帮助 。
需要的工具
能够和OpenStack持续集成平台协同的测试平台组件如下:
-
Jenkins CI
-
运行相关项目测试任务的服务器
-
Zuul
-
组织运行jenkins任务机制的系统
-
Jenkins Job Builder (JJB)
-
简化Jenkins任务配置文件的创建\维护工作
-
Devstack-Gate and Nodepool 脚本
-
从源码库构建OpenStack 环境的脚本
下面我会说明如何使用脚本和Puppet实现上述测试平台的组件功能. 当然还有其他的方法实现相同的功能。
可以根据文档手工安装相关组件. 但我不建议这么做,手动安装有利有弊:
- 一旦有地方出错,所有工作全部需要返工。如果之前做了什么配置修改,现在全凭记忆来恢复。
- 无法方便的建立新的测试平台示例.如果要实现就得全部从新配置
好的办法就是使用配置管理平台,比如 Puppet, Chef, Ansible or SaltStack 来管理组件的部署, 同时使用Git管理配置库。本文将 通过Bash脚本和Puppet modules实现在多个host或是虚拟机上构建测试平台。相关代码在 source repository on GitHub. 如果你不想用 Puppet或是想用其他的工具,也没啥问题. 从刚才的源码库中也能得到不少启发 (以后我还会写一些OpenStack 外部测试项目的脚本)。
预备
开始安装之前有几点需要注意:按照下述步骤操作应该没什么问题。
获取上游服务账户
为了能够发布测试平台的评审备注到 openstack.org, 需要先从 OpenStack Infra 团队注册一个账户. 详细如下 this link for instructions
简单来说需要向 OpenStack Infra mailing list 发送一份邮件,里面包含下述内容:
-
邮件地址作为系统账户(必须是唯一的Gerrit账户)
-
账户名缩写会显示在代码评审里
-
(可选) 账户详细描述
-
(可选但推荐) 联系方式 (IRC handle, 邮箱地址或是其它间接联系邮箱) 方便上游基础团队联系
-
访问Gerrit的SSH键值组公匙 . 注意SSH 中不要多出新代码行
还没有Gerrit服务账户的的SSH键值组? 可以创建一个:
ssh-keygen -t rsa -b 1024 -N '' -f gerrit_key
上面命令会生成一个兼职组: 被命名为gerrit_keyandgerrit_key.pub的文件. 将gerrit_key.pub中的内容通过邮件发送到 OpenStack Infra mailing list. 保留上述两个东西方便下面使用。
创建Git配置库
开始安装测试平台后Puppet modules会保存一系列系统的配置文件,包括Gerrit服务账户的SSH私匙。保存这些文件最理想的东西就是Git配置库了, 任何的变动都会被保存下来就想保存源码那样。
我开了一个账户 source repository on GitHub 作为示例. 和以往不同的是,我建议使用git clone代码到本地库使用,而不要使用fork的模式:
git clone git@github.com:jaypipes/os-ext-testing-data ~/mydatarepo cd mydatarepo rm -rf .git git init . git add . git commit -a -m "My new data repository"
现在就得到了一个本地的配置库来保存相关的配置文件,随便放在哪里都没问题 — 也许是 GitHub,甚至其它地方的Git服务器上。
将Gerrit服务账户私匙放到数据仓库里
现在要把上一步创建的访问Gerri 服务账户的键值组也放到仓库里。
如果用ssh-keygen命令创建了新的键值组. 也需要将gerrit_key文件拷贝到仓库里。
如果既没有创建新的键值组 (用的原来的) 或者名字不是 gerrit_key, 那就拷贝该文件到仓库再打开 vars.sh, 修改下述代码:
export UPSTREAM_GERRIT_SSH_KEY_PATH=gerrit_key
将gerrit_key 改成对应的SSH私匙名。
设置Gerrit 账户用户名
下面打开创库里的filevars.sh (假定你还没打开), 修改下面代码:
export UPSTREAM_GERRIT_USER=jaypipes-testing
把jaypipes-testing改成你的Gerrit账户名。
在Test Jenkins Job上设置供应商名称
打开 etc/jenkins_jobs/config/projects.yaml . 修改下面代码:
vendor: myvendor
把myvendor改成对应的组织名
(可选) 创建 Jenkins SSH 键值对
在数据仓中我有公有/私有的SSH键值对 (叫做jenkins_key[.pub]. 因为已经把私匙放过去了现在其实也没啥用,就当个例子吧。如果想建个新的,这样操作:
cd $DATA_DIRECTORY ssh-keygen -t rsa -b 1024 -N '' -f jenkins_key git commit -a -m "Changed jenkins key to a new private one"
保存数据仓库的更新
好的,现在已经处理好了数据仓库的配置可以开始安装Jenkins master服务器了. 但记住先保存一下相关的更改放到配置库里:
git add . git commit -a -m "Added Gerrit SSH key and username" git push
服务端的需求
在服务端(hosts, 虚拟机, 或LXC容器) 安装Jenkins master和slaves之前,检查下述条件:
- 相关包已被安装:
wget openssl ssl-cert ca-certificates
-
~/.ssh/里配置好了GitHub需要的SSH值. 这也会影响到~/.ssh/known_hosts 和~/.ssh/configfiles文件。
设置Jenkins Master 端
在需要安装Jenkins Master端的虚拟机 (或 LXC 容器) 执行下述动作:
git clone $YOUR_DATA_REPO data wget https://raw.github.com/jaypipes/os-ext-testing/master/puppet/install_master.sh bash install_master.sh
上边代码创建了SSL self-signed 认证以使Apache来运行Jenkins UI 并随之安装 Jenkins, Jenkins Job Builder, Zuul, Nodepool 脚本和其他相应的包文件.
注意: 就在写这篇文章的时候,Zuul 系统已经进行了一些重构 a bit of a refactoring, 所有Zuul git-相关的任务都通过名为 zuul-merger的进程来管理了. 我已经更新了库里的os-ext-testing 部分,如果你是在February 18th, 2014J之前从Puppet modules安装的Jenkins master 和Zuul , 你需要在 master端执行下述操作来重新配置:
# NOTE: This is only necessary if you installed a Jenkins master from the # os-ext-testing repository before Tuesday, February 18th, 2014! sudo service zuul stop sudo rm -rf /var/log/zuul/* /var/run/zuul/* sudo -i # As root... cd /root/config; git pull /root/config exit cd os-ext-testing; git pull; cd ../ cp os-ext-testing/puppet/install_master.sh . bash install_master.sh
Puppet完了后,访问http://$HOST_IP:8080打开Jenkins界面。 启用 Zuul 和Jenkins 交互的Gearman workers:
- 点左边的链接 `Manage Jenkins`
- 点 `Configure System` 链接
- 下拉到 “Gearman Plugin Config”. 勾上“Enable Gearman”
- 点 “Test Connection” 按钮并确认 Jenkins已连接到Gearman
- 下拉到页面底端点 `Save`
Note: Darragh O’Reilly里提到在他机器上首次安装Gearman plugin 无法使用(尽管确实安装过了). 这时仅需要重启Jenkins服务就能解决该问题, 之后在 Manage Jenkins -> Configure页面配置启用Gearman Plugin 。
完成上述操作后启动Jenkins任务并启动 Zuul:
sudo jenkins-jobs --flush-cache update /etc/jenkins_jobs/config/ sudo service zuul start sudo service zuul-merger start
刷新Jenkins 界面后出现相关的两个任务:
Jenkins Master 界面显示Sandbox 任务是由JJB创建的。
测试 Master端和上游的通信情况
祝贺你成功部署了Jenkins master端. 现在用 sandbox-noop-check-communication 任务测一下测试平台和上游的通信状况. 默认情况下我配置任务执行 openstack-dev/sandbox 项目[1]. 这是配置库里相关的配置etc/jenkins_jobs/config/projects.yamlfile:
- project: name: sandbox github-org: openstack-dev node: master jobs: - noop-check-communication - dsvm-tempest-full: node: devstack_slave
默认端是master . sandbox-dsvm-tempest-full运行在devstack_slave上, 等后面涉及到在细说。
在Zuul的配置里有两个管道: check 和gate. 下面只有一个openstack-dev/sandbox的简单项目情况 layout.yaml Zuul project configuration file,:
projects: - name: openstack-dev/sandbox check: - sandbox-noop-check-communication
默认情况下只有sandbox-noop-check-communication 任务运行, 并在openstack-dev/sandbox 项目打了新补丁, 或是提交了含有 “recheck no bug” 或“recheck bug XXXXX”字样评注的情况下被触发. 那咱们建一个项目的补丁看看sandbox-noop-check-communication任务是不是正确执行了。
操作之前先tail上 Zuul的调试日志, 过滤出 “sandbox”. 这样更方便查看通讯任务的进展情况:
sudo tail -f /var/log/zuul/debug.log | grep sandbox
创建一个sandbox补丁. 注意是在工作区创建而不是Jenkins上:
git clone git@github.com:openstack-dev/sandbox /tmp/sandbox cd /tmp/sandbox git checkout -b testing-ext touch mytest git add mytest git commit -a -m "Testing comms" git review
输出结果如下:
jaypipes@cranky:~$ git clone git@github.com:openstack-dev/sandbox /tmp/sandbox Cloning into '/tmp/sandbox'... remote: Reusing existing pack: 13, done. remote: Total 13 (delta 0), reused 0 (delta 0) Receiving objects: 100% (13/13), done. Resolving deltas: 100% (4/4), done. Checking connectivity... done jaypipes@cranky:~$ cd /tmp/sandbox jaypipes@cranky:/tmp/sandbox$ git checkout -b testing-ext Switched to a new branch 'testing-ext' jaypipes@cranky:/tmp/sandbox$ touch mytest jaypipes@cranky:/tmp/sandbox$ git add mytest jaypipes@cranky:/tmp/sandbox$ git commit -a -m "Testing comms" [testing-ext 51f90e3] Testing comms 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 mytest jaypipes@cranky:/tmp/sandbox$ git review Creating a git remote called "gerrit" that maps to: ssh://jaypipes@review.openstack.org:29418/openstack-dev/sandbox.git Your change was committed before the commit hook was installed. Amending the commit to add a gerrit change id. remote: Processing changes: new: 1, done remote: remote: New Changes: remote: https://review.openstack.org/73631 remote: To ssh://jaypipes@review.openstack.org:29418/openstack-dev/sandbox.git * [new branch] HEAD -> refs/publish/master/testing-ext
盯好Zuul的调试日志,如果没什么问题应看到下面的内容:
2014-02-14 16:08:51,437 INFO zuul.Gerrit: Updating information for 73631,1 2014-02-14 16:08:51,629 DEBUG zuul.Gerrit: Change status: NEW 2014-02-14 16:08:51,630 DEBUG zuul.Scheduler: Adding trigger event: 2014-02-14 16:08:51,630 DEBUG zuul.Scheduler: Done adding trigger event: 2014-02-14 16:08:51,630 DEBUG zuul.Scheduler: Run handler awake 2014-02-14 16:08:51,631 DEBUG zuul.Scheduler: Fetching trigger event 2014-02-14 16:08:51,631 DEBUG zuul.Scheduler: Processing trigger event 2014-02-14 16:08:51,631 DEBUG zuul.IndependentPipelineManager: Starting queue processor: check 2014-02-14 16:08:51,631 DEBUG zuul.IndependentPipelineManager: Finished queue processor: check (changed: False) 2014-02-14 16:08:51,631 DEBUG zuul.DependentPipelineManager: Starting queue processor: gate 2014-02-14 16:08:51,631 DEBUG zuul.DependentPipelineManager: Finished queue processor: gate (changed: False)
如果现在去看看 Gerrit 的评注链接里(运行git review后出来的结果链接), 会有一个+1的 Verified vote :
通讯成功!
好了,现在就实现了一个从Gerrit获取更新事件之后触发持续集成服务器执行相关任务再将任务结果返回 Gerrit系统的全过程外部测试平台了。 接下来的文章讲一下如何添加Jenkins子系统next article goes over adding a Jenkins slave to your system, 以便实现devstack-based gate 测试. 如果有任何关于本文或是实现过程中脚本的建议意见,恳请告知!
The OpenStack Sandbox 项目是用来测试外部测试平台和上游任务的集成情况的。一旦提交了新的补丁,将会自动触发文中设置好的Jenkins任务。