如何構(gòu)建一個外部的 OpenStack 測試系統(tǒng)?
本文介紹如何構(gòu)建與 OpenStack continuous integration platform貫穿的測試平臺。開始前最好對本文upstream OpenStack CI platform in detail中的背景有所了解。讀完本文后,你將具備構(gòu)建測試平臺所需的所有背景知識。
測試平臺干嘛的?
簡單的說,就是 運行第三方的獨立測試 — 通過將三方驅(qū)動或硬件配置到 OpenStack 環(huán)境中 — 然后在代碼審查的過程中展示相關(guān)的測試報告. 通過這個實時的代碼審查回饋能很容易的把控代碼質(zhì)量. 下圖中,你會看到Neutron的外部測試平臺加入的numberVerified +1 and one Verified -1 標(biāo)簽:
測試平臺引入的Verified +1 and -1 標(biāo)簽
每添加一個新的標(biāo)簽就會產(chǎn)生一條comments,點擊注釋就會鏈接到測試平臺上的相關(guān)測試:
Comments 對應(yīng)著一次測試平臺的review
開發(fā)人員可以通過訪問相應(yīng)的鏈接去排查造成測試平臺失敗的相關(guān)補(bǔ)丁問題。
為啥需要外部測試平臺?
好處有如下幾點:
-
及時獲得反饋
-
測試平臺能提早發(fā)現(xiàn)相關(guān)補(bǔ)丁提交后可能造成的失敗,這能縮短問題解決時間
-
更好的代碼覆蓋率
-
通過模擬測試插件和驅(qū)動程序來減少對真實測試環(huán)境的依賴。以此為開發(fā)人員提供更多的時間專注于業(yè)務(wù)代碼的質(zhì)量
-
持續(xù)提高質(zhì)量標(biāo)準(zhǔn)
-
通過相關(guān)用例來測試部分或者全部的驅(qū)動程序API以保證與OpenStack的兼容性. 如果你和OpenStack的開發(fā)人員聊過,就會知道他們面對如何選擇存儲或網(wǎng)絡(luò)供應(yīng)商或是后臺管理模式去兼容將要部署的 OpenStack問題時,這一優(yōu)勢會多么明顯!
何必再去思考如何選擇測試平臺的問題? 已經(jīng)大把OpenStack項目和供應(yīng)商探討過集成測試平臺到上游的OpenStack持續(xù)集成平臺的需求了。Neutron開發(fā)社區(qū)已經(jīng)走在前面 ahead of the game,大約快一打的供應(yīng)商已經(jīng)在Neutron代碼審查中加入了測試的鏈接.
Cinder項目在討論 discussions 強(qiáng)制推行一有代碼提交就測試驅(qū)動的正確性策略。 同樣的,Nova 社區(qū)也討論了 discussed 監(jiān)控源碼庫的相關(guān)策略. 也許這對于有些團(tuán)隊來說不是什么新鮮事, 帶希望本文能給新接觸 OpenStack的供應(yīng)商們提供更快融入的幫助 。
需要的工具
能夠和OpenStack持續(xù)集成平臺協(xié)同的測試平臺組件如下:
-
Jenkins CI
-
運行相關(guān)項目測試任務(wù)的服務(wù)器
-
Zuul
-
組織運行jenkins任務(wù)機(jī)制的系統(tǒng)
-
Jenkins Job Builder (JJB)
-
簡化Jenkins任務(wù)配置文件的創(chuàng)建\維護(hù)工作
-
Devstack-Gate and Nodepool 腳本
-
從源碼庫構(gòu)建OpenStack 環(huán)境的腳本
下面我會說明如何使用腳本和Puppet實現(xiàn)上述測試平臺的組件功能. 當(dāng)然還有其他的方法實現(xiàn)相同的功能。
可以根據(jù)文檔手工安裝相關(guān)組件. 但我不建議這么做,手動安裝有利有弊:
- 一旦有地方出錯,所有工作全部需要返工。如果之前做了什么配置修改,現(xiàn)在全憑記憶來恢復(fù)。
- 無法方便的建立新的測試平臺示例.如果要實現(xiàn)就得全部從新配置
好的辦法就是使用配置管理平臺,比如 Puppet, Chef, Ansible or SaltStack 來管理組件的部署, 同時使用Git管理配置庫。本文將 通過Bash腳本和Puppet modules實現(xiàn)在多個host或是虛擬機(jī)上構(gòu)建測試平臺。相關(guān)代碼在 source repository on GitHub. 如果你不想用 Puppet或是想用其他的工具,也沒啥問題. 從剛才的源碼庫中也能得到不少啟發(fā) (以后我還會寫一些OpenStack 外部測試項目的腳本)。
預(yù)備
開始安裝之前有幾點需要注意:按照下述步驟操作應(yīng)該沒什么問題。
獲取上游服務(wù)賬戶
為了能夠發(fā)布測試平臺的評審備注到 openstack.org, 需要先從 OpenStack Infra 團(tuán)隊注冊一個賬戶. 詳細(xì)如下 this link for instructions
簡單來說需要向 OpenStack Infra mailing list 發(fā)送一份郵件,里面包含下述內(nèi)容:
-
郵件地址作為系統(tǒng)賬戶(必須是唯一的Gerrit賬戶)
-
賬戶名縮寫會顯示在代碼評審里
-
(可選) 賬戶詳細(xì)描述
-
(可選但推薦) 聯(lián)系方式 (IRC handle, 郵箱地址或是其它間接聯(lián)系郵箱) 方便上游基礎(chǔ)團(tuán)隊聯(lián)系
-
訪問Gerrit的SSH鍵值組公匙 . 注意SSH 中不要多出新代碼行
還沒有Gerrit服務(wù)賬戶的的SSH鍵值組? 可以創(chuàng)建一個:
ssh-keygen -t rsa -b 1024 -N '' -f gerrit_key
上面命令會生成一個兼職組: 被命名為gerrit_keyandgerrit_key.pub的文件. 將gerrit_key.pub中的內(nèi)容通過郵件發(fā)送到 OpenStack Infra mailing list. 保留上述兩個東西方便下面使用。
創(chuàng)建Git配置庫
開始安裝測試平臺后Puppet modules會保存一系列系統(tǒng)的配置文件,包括Gerrit服務(wù)賬戶的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"
現(xiàn)在就得到了一個本地的配置庫來保存相關(guān)的配置文件,隨便放在哪里都沒問題 — 也許是 GitHub,甚至其它地方的Git服務(wù)器上。
將Gerrit服務(wù)賬戶私匙放到數(shù)據(jù)倉庫里
現(xiàn)在要把上一步創(chuàng)建的訪問Gerri 服務(wù)賬戶的鍵值組也放到倉庫里。
如果用ssh-keygen命令創(chuàng)建了新的鍵值組. 也需要將gerrit_key文件拷貝到倉庫里。
如果既沒有創(chuàng)建新的鍵值組 (用的原來的) 或者名字不是 gerrit_key, 那就拷貝該文件到倉庫再打開 vars.sh, 修改下述代碼:
export UPSTREAM_GERRIT_SSH_KEY_PATH=gerrit_key
將gerrit_key 改成對應(yīng)的SSH私匙名。
設(shè)置Gerrit 賬戶用戶名
下面打開創(chuàng)庫里的filevars.sh (假定你還沒打開), 修改下面代碼:
export UPSTREAM_GERRIT_USER=jaypipes-testing
把jaypipes-testing改成你的Gerrit賬戶名。
在Test Jenkins Job上設(shè)置供應(yīng)商名稱
打開 etc/jenkins_jobs/config/projects.yaml . 修改下面代碼:
vendor: myvendor
把myvendor改成對應(yīng)的組織名
(可選) 創(chuàng)建 Jenkins SSH 鍵值對
在數(shù)據(jù)倉中我有公有/私有的SSH鍵值對 (叫做jenkins_key[.pub]. 因為已經(jīng)把私匙放過去了現(xiàn)在其實也沒啥用,就當(dāng)個例子吧。如果想建個新的,這樣操作:
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"
保存數(shù)據(jù)倉庫的更新
好的,現(xiàn)在已經(jīng)處理好了數(shù)據(jù)倉庫的配置可以開始安裝Jenkins master服務(wù)器了. 但記住先保存一下相關(guān)的更改放到配置庫里:
git add . git commit -a -m "Added Gerrit SSH key and username" git push
服務(wù)端的需求
在服務(wù)端(hosts, 虛擬機(jī), 或LXC容器) 安裝Jenkins master和slaves之前,檢查下述條件:
- 相關(guān)包已被安裝:
wget openssl ssl-cert ca-certificates
-
~/.ssh/里配置好了GitHub需要的SSH值. 這也會影響到~/.ssh/known_hosts 和~/.ssh/configfiles文件。
設(shè)置Jenkins Master 端
在需要安裝Jenkins Master端的虛擬機(jī) (或 LXC 容器) 執(zhí)行下述動作:
git clone $YOUR_DATA_REPO data wget https://raw.github.com/jaypipes/os-ext-testing/master/puppet/install_master.sh bash install_master.sh
上邊代碼創(chuàng)建了SSL self-signed 認(rèn)證以使Apache來運行Jenkins UI 并隨之安裝 Jenkins, Jenkins Job Builder, Zuul, Nodepool 腳本和其他相應(yīng)的包文件.
注意: 就在寫這篇文章的時候,Zuul 系統(tǒng)已經(jīng)進(jìn)行了一些重構(gòu) a bit of a refactoring, 所有Zuul git-相關(guān)的任務(wù)都通過名為 zuul-merger的進(jìn)程來管理了. 我已經(jīng)更新了庫里的os-ext-testing 部分,如果你是在February 18th, 2014J之前從Puppet modules安裝的Jenkins master 和Zuul , 你需要在 master端執(zhí)行下述操作來重新配置:
# 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” 按鈕并確認(rèn) Jenkins已連接到Gearman
- 下拉到頁面底端點 `Save`
Note: Darragh O’Reilly里提到在他機(jī)器上首次安裝Gearman plugin 無法使用(盡管確實安裝過了). 這時僅需要重啟Jenkins服務(wù)就能解決該問題, 之后在 Manage Jenkins -> Configure頁面配置啟用Gearman Plugin 。
完成上述操作后啟動Jenkins任務(wù)并啟動 Zuul:
sudo jenkins-jobs --flush-cache update /etc/jenkins_jobs/config/ sudo service zuul start sudo service zuul-merger start
刷新Jenkins 界面后出現(xiàn)相關(guān)的兩個任務(wù):
Jenkins Master 界面顯示Sandbox 任務(wù)是由JJB創(chuàng)建的。
測試 Master端和上游的通信情況
祝賀你成功部署了Jenkins master端. 現(xiàn)在用 sandbox-noop-check-communication 任務(wù)測一下測試平臺和上游的通信狀況. 默認(rèn)情況下我配置任務(wù)執(zhí)行 openstack-dev/sandbox 項目[1]. 這是配置庫里相關(guān)的配置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
默認(rèn)端是master . sandbox-dsvm-tempest-full運行在devstack_slave上, 等后面涉及到在細(xì)說。
在Zuul的配置里有兩個管道: check 和gate. 下面只有一個openstack-dev/sandbox的簡單項目情況 layout.yaml Zuul project configuration file,:
projects: - name: openstack-dev/sandbox check: - sandbox-noop-check-communication
默認(rèn)情況下只有sandbox-noop-check-communication 任務(wù)運行, 并在openstack-dev/sandbox 項目打了新補(bǔ)丁, 或是提交了含有 “recheck no bug” 或“recheck bug XXXXX”字樣評注的情況下被觸發(fā). 那咱們建一個項目的補(bǔ)丁看看sandbox-noop-check-communication任務(wù)是不是正確執(zhí)行了。
操作之前先tail上 Zuul的調(diào)試日志, 過濾出 “sandbox”. 這樣更方便查看通訊任務(wù)的進(jìn)展情況:
sudo tail -f /var/log/zuul/debug.log | grep sandbox
創(chuàng)建一個sandbox補(bǔ)丁. 注意是在工作區(qū)創(chuàng)建而不是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
輸出結(jié)果如下:
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的調(diào)試日志,如果沒什么問題應(yīng)看到下面的內(nèi)容:
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)
如果現(xiàn)在去看看 Gerrit 的評注鏈接里(運行g(shù)it review后出來的結(jié)果鏈接), 會有一個+1的 Verified vote :
通訊成功!
好了,現(xiàn)在就實現(xiàn)了一個從Gerrit獲取更新事件之后觸發(fā)持續(xù)集成服務(wù)器執(zhí)行相關(guān)任務(wù)再將任務(wù)結(jié)果返回 Gerrit系統(tǒng)的全過程外部測試平臺了。 接下來的文章講一下如何添加Jenkins子系統(tǒng)next article goes over adding a Jenkins slave to your system, 以便實現(xiàn)devstack-based gate 測試. 如果有任何關(guān)于本文或是實現(xiàn)過程中腳本的建議意見,懇請告知!
The OpenStack Sandbox 項目是用來測試外部測試平臺和上游任務(wù)的集成情況的。一旦提交了新的補(bǔ)丁,將會自動觸發(fā)文中設(shè)置好的Jenkins任務(wù)。