建立一個外部的 OpenStack 測試系統

類別: IT

本文介紹如何構建與 OpenStack continuous integration platform貫穿的測試平臺。開始前最好對本文upstream OpenStack CI platform in detail中的背景有所瞭解. 讀完本文後,你將具備構建測試平臺所需的所有背景知識。

測試平臺幹嘛的?

簡單的說,就是 執行第三方的獨立測試 — 通過將三方驅動或硬體配置到 OpenStack 環境中 — 然後在程式碼審查的過程中展示相關的測試報告. 通過這個實時的程式碼審查回饋能很容易的把控程式碼質量. 下圖中,你會看到Neutron的外部測試平臺加入的numberVerified +1 and one Verified -1 標籤 :

Verified +1 and -1 labels added by external testing systems on a Neutron patch

測試平臺引入的Verified +1 and -1 標籤

每新增一個新的標籤就會產生一條comments. 點選註釋就會連結到測試平臺上的相關測試:

Comments added to a review by the vendor testing platforms

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實現上述測試平臺的元件功能. 當然還有其他的方法實現相同的功能。

可以根據文件手工安裝相關元件. 但我不建議這麼做,手動安裝有利有弊:

  1. 一旦有地方出錯,所有工作全部需要返工。如果之前做了什麼配置修改,現在全憑記憶來恢復。

  2. 無法方便的建立新的測試平臺示例.如果要實現就得全部從新配置

好的辦法就是使用配置管理平臺, 比如 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 [email protected]: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. :

  1. 點左邊的連結 `Manage Jenkins` 

  2. 點  `Configure System` 連結 

  3. 下拉到 “Gearman Plugin Config”. 勾上“Enable Gearman” .

  4. 點  “Test Connection” 按鈕並確認 Jenkins已連線到Gearman.

  5. 下拉到頁面底端點 `Save`

  6. 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
  7. 重新整理Jenkins 介面後出現相關的兩個任務:

    Jenkins Master Web UI Showing Sandbox Jenkins Jobs Created by JJB

    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的配置裡有兩個管道: checkgate. 下面只有一個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 [email protected]: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

輸出結果如下:

[email protected]:~$ git clone [email protected]: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
[email protected]:~$ cd /tmp/sandbox
[email protected]:/tmp/sandbox$ git checkout -b testing-ext
Switched to a new branch 'testing-ext'
[email protected]:/tmp/sandbox$ touch mytest
[email protected]:/tmp/sandbox$ git add mytest
[email protected]:/tmp/sandbox$ git commit -a -m "Testing comms"
[testing-ext 51f90e3] Testing comms
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 mytest
[email protected]:/tmp/sandbox$ git review
Creating a git remote called "gerrit" that maps to:
	ssh://[email protected]: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://[email protected]: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 :

Successful communication between upstream and our external system

通訊成功

好了,現在就實現了一個從Gerrit獲取更新事件之後觸發持續整合伺服器執行相關任務再將任務結果返回 Gerrit系統的全過程外部測試平臺了。 接下來的文章講一下如何新增Jenkins子系統next article goes over adding a Jenkins slave to your system, 以便實現devstack-based gate 測試. 如果有任何關於本文或是實現過程中指令碼的建議意見,懇請告知! :)

[1]— The OpenStack Sandbox 專案是用來測試外部測試平臺和上游任務的整合情況的. 一旦提交了新的補丁,將會自動觸發文中設定好的Jenkins任務

建立一個外部的 OpenStack 測試系統原文請看這裡

推薦文章