2016年1月14日 星期四

以 SOLVCON 專案為例,使用 conda 來維護、建立 python 執行與開發環境

一套可以正常運作的應用程式往往需要有很多其他配套的軟體互相支援,這造成了建構軟體中常見的「版本相依性」問題。如果是使用者的身份,這類問題可以透過(雖然這不一定是最好的方法)將所有相依的軟體都打成一包釋出。但身為開發者,常常遇到的問題是「開發者自己的作業系統環境」和「想開發的應用程式所需要的環境」有所不同。一般來說,開發者大概不太願意去更動自己的作業系統環境來配合自己的開發標的軟體,因為這可能會導致開發者自己的作業系統本身、或是作業系統下的其他應用程式無法正常運作。一個直觀的解決方案當然就是「那我弄一個專門給想開發的軟體使用的環境總可以了吧?」,conda 就是這樣的一個工具。

conda 是 anaconda 和 miniconda 所羅列的工具之一 。anaconda 和 miniconda 也是想做一樣的事情,但是前者可以堪稱是「包山包海」;這是優點也是缺點,優點就是一口氣把所有第三方的軟體都先準備好,以後幾乎不用再煩惱,缺點就是一定會準備了很多其實用不到的東西。miniconda 可以想像成是精簡版本的 anaconda 、然後有管理 python package 功能的 virtualenv[1]。

最近 SOLVCON 從原來的 python 2 移植到 python 3 ,主要的核心移植已經堪稱完成。然而最近想持續開發的 parallel 運算能力則在移植前便已經過時,剛好趁這次大搬家把這個 feature 修回來。

要熟悉一個程式的 feature,我還滿喜歡從研究它相關的 unittest 開始著手。理由如下:

從 unittest 中,我們可以看到
  1. 使用者的角度 - 這個功能如何被使用
  2. 測試者的角度 - 這個功能所產生的結果如何被解讀
有頭(如何 input 和使用)有尾(如何解讀 output)的情況下,就可以開始從外部行為來觀察程式執行 runtime 這個可以被視為黑盒子的部份。可以觀察外在的行為(unittest)加上可以觀察內在的行為(例如 source code)的話,幾乎就是一個說明清楚的 step by step tutorial。

有點扯太遠,總而言之要處理下面這兩件事情:
  1. 準備可以運行的 SOLVCON。SOLVCON 不再使用 scons 做套件管理(悲劇!!打包成 debian package 的 rule file 又要重寫 XD ),而改為使用 python setuptool ;因此要把對應的第三方工具告訴 setuptool。這裡我們採用 conda 當作解決方案。
  2. 利用 ftests 中的 nosetest 去研究和修復 SOLVCON 的平行運算功能。

準備好 conda 之後(這部份略過啦!好久以前就裝好了 XD 裝 anaconda 或是 miniconda 之後就有這個指令可以使用),先確認環境變數有告訴系統哪裡去找 conda 這個工具(通常是 anaconda 或是 miniconda 當初安裝的位置),例如有加入 PATH 變數。

啟動並且進入 conda 環境;我自己是把他寫成一個 alias 比較方便
alias solvconenv="export PATH=$MYLOCALINSTALLATION/miniconda3/solvcon-dev/bin:$PATH; source activate $MYLOCALINSTALLATION/miniconda3/solvcon-dev"

接著使用這個指令去安裝缺少的套件
conda search <package name>

安裝則是
conda install <package name>

例如安裝 python
conda install python
安裝 python3
conda install python=3
後面的等於3表示指定特定版本號碼。


更多使用方法請見 help
conda -h

[1] virtualenv 是用來建立獨立 python 套件環境的工具。









2016年1月13日 星期三

使用 flake8_docstrings python package 將 docstring 格式納入 flake8 檢查項目

長久以來一直都習慣在 Ubuntu 下使用 flake8 這個工具來檢查自己 python source code 有沒有符合 pep8 規範。

在 Ubuntu 下安裝 flake8

sudo apt-get install python-flake8

使用

flake8 <your source code>

這個工具同時也可以和 vim 共用,使得使用者在用 vim 的時候可以即時看到檢查結果。(但我今天沒打算聊這個 XD)

但今天被強者我同事糾正我的 docstring 沒有符合規範,建議我可以使用 flake8-docstrings 這個工具將檢查更完善一些。我才注意到 1. Ubuntu 下沒有這個 package 2. 以往我都漏掉這個檢查了。於是趕緊補上:

因為 Ubuntu 沒有納入管理 flake8-docstring 這個套件,所以我改用 pip 安裝工具來安裝:


sudo pip install flake8_docstrings

安裝之後再使用 flake8 就可以看到它會去掃出不符合規範的 docstring 了,例如:

$ flake8 <my source code>
......
D300 Use """triple double quotes"""
D400 First line should end with a period
D102 Missing docstring in public method
......


環境:Ubuntu Trusty

2016年1月11日 星期一

使用虛擬機器測試 secure boot (四) 使用 OVMF

前面提到我們已經用 OVMF (open source virtual machine firmware)建立一個虛擬機器了。現在我們想要讓 OVMF 這個 firmware 啟動 secure boot ,並且可以讓我們放入自己的 key 。這樣之後就可以模擬真實的 secure boot 的情形。

方法主要參考這篇文章,另外再根據自己環境的情況做調整。

使用 virsh 重新啟動稍早建立的虛擬機器

virsh list --all
virsh start <domain name>

開啟螢幕

virt-viewer <domain name>

啟動後,會 pop up 「Tianocore」,這是因為 OVMF 是移植並且開源 Intel 開發的 Tianocore 這個 firmware。因為還沒有安裝作業系統、虛擬機器的硬碟中也沒有 efi binary,所以會進入 OVMF 的 UEFI shell。輸入 exit 跳出後會進入到設定的畫面。如圖一路可以選到使用檔案匯入 key 的選項。當然,現在什麼檔案都沒有。所以問題變成是,我們要怎麼準備 key file 呢?










2016年1月6日 星期三

使用虛擬機器測試 secure boot (三) 使用 virtsh


呼叫使用提示
virsh help

顯示選項 list 的使用提示
virsh help list

連結本地端 qemu 這個 hypervisor (virsh 可以管理多種不同的 hypervisor,qemu 只是其中一種)
virsh connect qemu:///system
連進去後,
顯示 domains (但 inactive domain 不會顯示;一開始還以為沒有連成功,因為啥都沒顯示)
virsh list

顯示 domains (包括 inactive domain)
virsh list --all

立刻終止 active domain (相當於 virt-manager 下使用 force off )
virsh destroy <domain name>

刪除已經建立/定義好的 domain(要先 destroy 才可以 undefine)
virsh undefine <domain name>

virt-tools.org 這裡有簡單的教學。



virt-tools.org 的這個教學網頁裡也有提到如何透過 /proc/cpuinfo and demsg 檢查自身的機器是否支援虛擬化技術;如果有,又是哪一種虛擬化技術。簡單直白,值得一看(下面直接摘要):

/proc/cpuinfo flags #

/proc/cpuinfo will tell you if the processor supports virtualization and if it is enabled (but it could not show up in flags because it is disabled — more on this below).
The flags to look out for are:
  • vmx — Intel VT-x, basic virtualization
  • svm — AMD SVM, basic virtualization
  • ept — Extended Page Tables, an Intel feature to make emulation of guest page tables faster.
  • vpid — VPID, an Intel feature to make expensive TLB flushes unnecessary when context switching between guests.
  • npt — AMD Nested Page Tables, similar to EPT.
  • tpr_shadow and flexpriority — Intel feature that reduces calls into the hypervisor when accessing the Task Priority Register, which helps when running certain types of SMP guests.
  • vnmi — Intel Virtual NMI feature which helps with certain sorts of interrupt events in guests.

Kernel messages (dmesg) and the BIOS #

The next thing to look at are the kernel messages by running the command:
dmesg | less
The two messages to look out for are:
kvm: no hardware support
and
kvm: disabled by bios




詞彙:
hypervisor - 不精確地講,就是虛擬機器層。
domain - virtual machine instance

使用虛擬機器測試 secure boot (二) virt tool 的介紹

上文中使用到的 virt-install 是 virt-tools 中的其中一個,也是 virt-manager 專案下的一個功能。下面簡單說明幾個常被用但是稍微有點被混淆的名詞:

OpenStack - 一個軟體專案。但這個軟體專案並不是典型開發或是維護一個軟體的那種專案,比較接近是「組合或是開發各種工具以提供某種 IaaS (infrastructure as a service) 服務的解決方案」。libvirt 是它支援的工具之一。

libvirt - 一套用 c 語言寫成的 API

virt tools - libvirt 與其週邊相關的工具、產品。包括 virt-manager 。

virt-manager - 這個詞有兩個意思,一個意思是有個指令叫做 virt-manager,可以提供 GUI 來管理基於 virt-manager 這個專案下支援的工具(例如 virt-install)所建立的虛擬機器。第二個意思就是這是一個專案的名稱,集成很多基於 libvirt 開發出的工具,例如 virt-install。

virsh - 可以想成是指令列版本的 virt-manager 工具。

下一篇:virsh 的使用!






使用虛擬機器測試 secure boot (一)

最近工作上開始需要自動化測試有開啟 secure boot 的機器,鴕鳥了好多年終於開始要好好面對這件事情了 XD

下面是跟著這篇 wiki 的資訊所作的測試。有些指令我有根據自己的狀況(host machine:Ubuntu Trusty)調整。覺得太繁瑣的話可以直接跳到幾乎是最後面的小結 XDD

因為我的系統中沒有 uvt 這個指令,找了一下沒有看到 uvt 這個指令從哪來,所以採用 wiki 中提供的另外一種作法:

virt-install --connect=qemu:///system --name=sb-saucy-amd64 --arch=x86_64 --ram=768 \
--disk=path=<path to>/sb-saucy-amd64.qcow2,size=8,format=qcow2,bus=ide,sparse=True \
--virt-type=kvm --accelerate --hvm --cdrom=<path to>/saucy-desktop-amd64.iso \
--os-type=linux --os-variant=generic26 --graphics=vnc --network=network=default,model=virtio \
--video=cirrus --noreboot --boot=loader=OVMF.fd

但會得到:

ERROR    Format cannot be specified for unmanaged storage.

這看起來似乎是要事先先建立好給虛擬機器使用的 storage file。因為急著想要看到結果,我使用 --nodisk 來取代 --disk [1]

virt-install --connect=qemu:///system --name=sb-trusty-amd64-02 --arch=x86_64 --ram=768 --nodisk --virt-type=kvm --accelerate --hvm --cdrom=./uuu/ubuntu-14.04.2-desktop-amd64.iso --os-type=linux --os-variant=generic26 --graphics=vnc --network=network=default,model=virtio --video=cirrus --noreboot --boot=loader=OVMF.fd
如果遇到這個訊息

Starting install...
Creating domain...                                                                                                                                                                    |    0 B     00:00  
WARNING  Unable to connect to graphical console: virt-viewer not installed. Please install the 'virt-viewer' package.
Domain installation still in progress. You can reconnect to
the console to complete the installation process.

表示要安裝 virt-veiwer package 來顯示開機過程的畫面:

sudo apt-get install virt-viewer

接下來就會看到開機畫面啦!

下一篇打算來解釋細節,敬請期待。









要印螢幕的時候按了 alt ,鍵盤的訊號同時被 host machine 和 guest machine 捕捉到的一瞬間 XD




















根據這封 virt-tool mailing list 中的 email,這是因為我們沒有事先告訴 virt-manager (or virtsh) 使用的 disk storage 存放位置(專有名詞叫做「pool」,一個 pool 下面可以有好幾個 storage file。),所以 virt-manager 認為這個地方它不敢亂動。

首先綁定資料夾 /tmp 成為 pool 之一,名字叫做 tmppool 的 pool

virsh pool-define-as --name tmppool --type dir --target /tmp

啟動 pool

virsh pool-start tmppool

接下來把上面一長串中 --disk 選項後面指定的位置改為 /tmp (新的 pool 位置)就可以用了:

$ virt-install --connect=qemu:///system --name=thho-trusty-amd64-01 --arch=x86_64 --ram=768 --disk=path=/tmp/thho-trusty-amd64.qcow2,size=8,format=qcow2,bus=ide,sparse=True --virt-type=kvm --accelerate --hvm --cdrom=./uuu/ubuntu-14.04.2-desktop-amd64.iso --os-type=linux --os-variant=generic26 --graphics=vnc --network=network=default,model=virtio --video=cirrus --noreboot --boot=loader=OVMF.fd
Starting install...
Allocating 'thho-trusty-amd64.qcow2'                                                                                                                                                  | 8.0 GB     00:00  
Creating domain...  

檢查 pool 相關的指令有哪些
virsh help pool

驗證一下是不是真的多了 tmppool 這個 pool

$ virsh pool-list
 Name                 State      Autostart
-------------------------------------------
 default              active     yes    
 tmppool              active     no      
 uvtool               active     yes  

使用 virt-install 建立新的 virtual machine instance (domain) 之後,我們只選 try ubuntu 但是不安裝,然後關機 or reboot。下一次只要直接使用 connect 和 start 就可以開啟虛擬機器了(這兩個動作請見下篇解釋)

virsh --connect qemu:///system start thho-trusty-amd64-01

啟動後因為不像 virt-install 一樣有自己啟動 virt-viewer ,所以要自己開:

virt-viewer thho-trusty-amd64-01

(thho-trusty-amd64-01 是 domain name)

開啟了之後就會進入 UEFI shell 如圖。





因為 storage (可以想成是虛擬硬碟)中我們還沒有安裝任何作業系統(上面只選 try ubuntu 但沒有安裝),所以開機後會進入 UEFI shell。這個 shell 是 ovmf 提供的。




比較:
所有指令和選項都一樣,但把  --boot=loader=OVMF.fd 拿掉。
也就是說我們預期不使用 OVMF.fd 這個 bootloader 開機,所以應該要直接進入使用 cdrom 開機。

virt-install --connect=qemu:///system --name=thho-trusty-amd64-02 --arch=x86_64 --ram=768 --disk=path=/tmp/thho-trusty-amd64-02.qcow2,size=8,format=qcow2,bus=ide,sparse=True --virt-type=kvm --accelerate --hvm --cdrom=./uuu/ubuntu-14.04.2-desktop-amd64.iso --os-type=linux --os-variant=generic26 --graphics=vnc --network=network=default,model=virtio --video=cirrus --noreboot

果然直接進入 cdrom iso






小結:

  • 使用 virt-install 建立虛擬機器。並且是建立一個擁有 ovmf 這個韌體的虛擬機器。
  • 使用 virsh 啟動 virt-install 建立的虛擬機器,開始操作 ovmf 提供的 UEFI shell。





因為我有打算在不久的將來自動化這些指令,所以刻意選擇使用 virsh 而不是 virt-manager。virt-manger 應該也是可以作到上面說的這些事情,只是在自動化上大概就會遇到問題。

2016年1月5日 星期二

初探 ipython parallel

最近為了開發 SOLVCON 平行運算的功能,開始評估可能的解決方案。這一塊自己的知識趨近於零 XD 有點亂槍打鳥地亂看,想看看別的專案怎麼設計的,看是要模仿、參考或是甚至直接拿來用的可能性如何。

下面簡單摘要這個頁面關於 ipython parallel 的介紹:

指令列輸入這個指令,建立四個 ipython kernel 給接下來的運算使用:
ipcluster start -n 4 

然後開始玩 hello world:

In [1]: from IPython.parallel import Client
In [2]: c = Client()
In [4]: c.ids
Out[4]: set([0, 1, 2, 3])
In [5]: c[:].apply_sync(lambda : "Hello, World")
Out[5]: [ 'Hello, World', 'Hello, World', 'Hello, World', 'Hello, World' ]
ipython parallel 中很多組態設定和通訊方式是採用 JSON (或是可以轉成 JSON 的 data object)的格式,例如這資料夾下面的東西:

~/.ipython/profile_default/security/




給 kvm 虛擬機器增加 USB 儲存裝置

最近為了開發給在 Snappy 架構下的 Ubuntu Core 用的、可以自動化 USB storage 讀寫測試的工具,採用了 kvm 虛擬機器作為開發環境。因為要測試標的是 USB ,所以花了一點時間了解了一下如何連結實體的 USB storage 裝置到使用 kvm 啟動的 image 。

在 Ubuntu desktop 下使用指令:

sudo kvm -m 512 -redir :8090::80 -redir :8022::22 the-image-you-want-to-test.img -usb -device usb-host,hostbus=2,hostaddr=11

要注意的是指定最後面兩個參數的值時比較麻煩,因為該值會根據 host machine 的狀態而改變。我自己是這樣找對應的值:

  1. 插入 USB storage
  2. 使用指令 lsusb 去看上面的 Bus and Device number ,把這兩個數字記下
  3. 退出 USB storage
  4. 啟動 kvm ,啟動時,根據上面的 Bus and Device number 分別填數 hostbus and hostaddr 。要注意的是這時候 hostaddr 要加 1 (因為重新插拔了一次。現在的 Linux kernel 會給裝置編號加一表示是新找到的裝置,用來和前一次區隔)
  5. 這時候再插入 USB storage ,原本在 host machine 會自動掛載的行為不會發生(推測 event signal 被 kvm 攔下來了);稍候也可以看到在 guest machine 中的 dmesg 指令指出有新的 USB storage 插入了。