如何構建一個外部的 OpenStack 測試系統?
本文介紹如何構建與 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任務。