2017年7月3日 星期一

hack 完 iso 之後怎麼讓他從 usb 開機?(提示:使用 isohybrid 技術)


概述

到了最近才了解原來 live USB (用 USB 開機、甚至在 USB 裡面裝作業系統隨時可以插拔的技術)能夠開機是靠著「騙」 BIOS 以為他在開軟碟機(對就是 5.2 吋、3.5 吋磁片的那種軟碟機;應該很多人沒有看過了吧 @@??)

原本早期用 CD 開機是(live CD):
BIOS --> 直接支援光碟機

live USB 的話就是:
BIOS --> 掃到 USB port,「以為」這是一個「插了光碟」的軟碟機 --> 基於軟碟機的規格、表頭去 chianload 到光碟的開機檔案

透過指令 apt-get source genisoimage 就可以看到實做原始碼;對原始碼查找 "floppy" 這個字眼就可以取得相關資訊。

實際可以用的工具

然而,如果只是單純將從光碟 dump 出來存成 iso9660 格式的檔案再倒入 USB device 的話,不能透過該 USB device 開機也只是剛好。因為 BIOS 認為他不是在光碟機的光碟、也沒有在硬碟(或是 block device)裡面可以讀懂並且用來開機的檔案(MBR boot sectors 或是 boot files in EFI partition)。

因此要做兩件事情:
* 在把 iso 倒入 usb device 的時候,要使用某種「從軟碟跳到 iso 相關檔案」的工具做 mapping - 由 genisoimage 提供
* 如何讓 BIOS 認為「這是一個有開機檔案的軟碟」 - 由 isohybrid 提供

大概是像這樣

files in folder --> <genisoimage> --> iso associated to MBR or EFI structure

iso associated to MBR/EFI --> <isobybrid> --> bootable iso

更多 genisoimage 和 isohybrid 的使用細節可以參考 [1]

實際應用


想要改動基於 gparted 做出的 debian image[2]。下載該 image、修改、壓回去然後用 usb 載入。

genisoimage -A "GParted Live CD" -V "GParted-live" -publisher "GParted http://gparted.org" -input-charset iso8859-1 -f -r -hide-rr-moved -hide-joliet-trans-tbl -J -l -allow-limited-size -b syslinux/isolinux.bin -c syslinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -efi-boot EFI/images/efiboot.img -no-emul-boot ./ > /tmp/gparted-live-amd64-iso8859-1.iso

上面的指令基本上含意如下,


-A "GParted Live CD" -V "GParted-live" -publisher "GParted http://gparted.org"

簡單的標籤名稱,很好理解

 -input-charset iso8859-1

檔案編碼,iso8859-1 是除了xx 以外常用的編碼,若是不指定就會用系統的

-f -r -hide-rr-moved -hide-joliet-trans-tbl -J -l -allow-limited-size

-b syslinux/isolinux.bin

isolinux binary image, 真正的開機 bootloader。指示要去哪裡找 isolinux.bin。

-c syslinux/boot.cat -no-emul-boot

boot.cat 就是 boot.catalog
參考 http://www.tldp.org/HOWTO/Bootdisk-HOWTO/cd-roms.html
模擬 floppy 的 image, 目的是把 BIOS 帶往 iso 真正用來開機的檔案(在這個案例是 isolinux.bin,因為我們上面的 -b 指示往要找 isolinux.bin)
要理解這個參數,請見上面的概述。
-no-emul-boot 指的是不要產生 floppy emulator image (就是 catalog, 因為已經有了,強制不要免得產生不預期的行為)

-boot-load-size 4

4 其實就對對應到一個硬碟磁區(sector)可能的位元組2*n, 對應一個典型 MBR 的大小 (128*4 = 512 bytes) ,這也是把開機會用到的檔案按照表頭指示的標準位置放置好而已。

-boot-info-table

塞 info table 進去 boot file(按照 EL TORITO spec,EL TORITO 規格是 iso9660 規格的擴充,是「可開機光碟」)


-eltorito-alt-boot
-efi-boot EFI/images/efiboot.img
-no-emul-boot ./

  • 後面這三個參數是三個一組,要一併使用。用來再生一個 iso filesystem (第二片光碟的意思,再這之前的選項生出給 MBR 格式用的,按照 MBR 會去找的位置放檔案),用於 UEFI 開機

到這邊就會打資料夾打包好變成一個符合 iso 9660 格式的 iso 檔案。最後再用 isohybrid 這個工具對此 iso 加工,使得我們可以引導 BIOS 把控制權交到 iso 中的那些可開機檔案(isolinux.bin 之類的)

isohybrid iso && isobybrid -u iso

前者使得 iso file 可以在 legacy mode 中開機,後者使得 iso file 可以在 UEFI mode 中開機。第一次 apply "isohybrid iso" 的時候,使用 disk 工具還看不到 EFI partition ,第二次 apply "isohybrid iso" 的時候,就可以看到 EFI partition 的結構出來了。

  • 題外話,稍微試了一下似乎
    • isohybrid iso && isobybrid -u iso
      • 可如預期開機(live usb 第二次完成後會有 EFI partition)
    • isobybrid -u iso && isohybrid iso
      • 不會如預期開機 (live usb 不會顯示 EFI partition)
    • 順序有關是有影響的。


最後把整個 iso dd 進去 usb stick 就可以了。

dd if=/tmp/$ISONAME of=/dev/sdb bs=4M && sync

零碎的資訊補充

  • genisoimage 就是 mkisofs 這個指令, 中間用 symbolic link

  • xorriso 就可以想成像是 genisoimage 和 isohbrid 兩個指令混合

題外話,曾經無意間發現 genisoimage 的功能限制(不太算是 bug),有回報在 Launchpad 上面 https://bugs.launchpad.net/ubuntu/+source/cdrkit/+bug/1475250 ,有空的話其實可以考慮送個 patch 增強一下該工具。

小結

整體而言,就是 "pack" ISO (get contents), and then make it bootable;要注意把原本可以 usb 開機的 iso 解開的時候往往已經拿掉 bootable 的資訊了,例如 bootable file and partition file system structure.



[1] http://www.syslinux.org/wiki/index.php?title=Isohybrid
[2] http://gparted.org/liveusb.php

2017年6月3日 星期六

Multi Boot Iso Live Usb


Multi Boot Iso Live Usb
主要參考這兩篇
  1. 事前準備
    • 建議使用 MBR partition table 和 FAT32
      • MBR partition 用於 legacy boot
      • FAT32 用於 UEFI boot
        • 一邊建議是 GPT + FAT32 來使用 UEFI,但因為我還想要有時候用 legacy boot 開機,所以故意選用 MBR。要支援 UEFI boot 的關鍵在 boot folder 是 FAT32 格式即可,之後的 boot image 都可以透過這裡的 bootloader binary 去尋找、啟動之。
  2. 軟體配置
    • 使用 grub install
    • copy iso
    • 準備對應每個 iso 的 grub.cfg

事前準備套件

sudo apt-get install grub-pc-bin grub-efi-amd64-bin
  • 注意因為只有裝 grub-efi-amd64-bin 所以僅限使用於 64 bit 的機器
      • 要設定 32 bit 的機器要另外裝別的套件

使用grub install

ubuntu@ubuntu:~$ sudo grub-install --removable --target=i386-pc --root-directory=/media/ubuntu/UsbStick/ /dev/sdc
Installation finished. No error reported.
ubuntu@ubuntu:~$ sudo grub-install --removable --target=x86_64-efi --root-directory=/media/ubuntu/UsbStick/ /dev/sdc
Installation finished. No error reported.
 * 參數說明
  * --removable
   * 用在可移除裝置,例如usb
  * --target
   * i386-pc 這選項是為了legacy開機
   * x86_64-efi 是為了efi開機
   * 想要有兩種開機能力都有那就兩個指令都要執行
 * 注意事項
  * fourdollar的文章中提到用ubuntu 13.04是因為13.04使用的grub是2.x版,早一點的grub(例如1.99)是沒有target這個選項的
  * /media/ubuntu/UsbStick/這種檔案架構是13.04採用的,12.04是類似/media/UsbStick/這樣
  * 當然grub中的--root-directory和裝置代號如/dev/sdc要根據實際的情形配置

tip: grub 的使用

  • 用 disk image 還原 hard disk,或是把系統硬碟換到不同的機器上的時候,也常常需要使用 grub-install 來修復、指定正確的 hard disk 位置
$ sudo grub-install --target=x86_64-efi --root-directory=/media/ubuntu/UsbStick/ /dev/sdc
如果有被抱怨找不到 EFI 資料夾,
檢查一下 /boot/efi 下面是不是有個叫 EFI 的資料夾。
Ubuntu 預設另外割一個 partition 並且 mount 在 /boot/efi
找不到有可能只是你在 grub-install 之前忘了先把這個 partition mount 上下
用下面的指令解決,/dev/sda1 是指 GPT 的特殊 partition
sudo mount /dev/sda1 /media/system-root-dir/boot/efi



內容這以前的 wikidot 移過來 http://tai271828.wikidot.com/multi-boot-iso-live-usb


2017年4月29日 星期六

淺談 Testflinger 的工作模型


原本的解決方案不符現在需求、也不適合大規模重構


隨著時間推移,業務型態也跟著逐漸改變。從只需要單純大量測試原生 Ubuntu 逐漸轉變到現在發展中、需要測試各種 Ubuntu 在各種平台上的表現。原本負責大量原生 Ubuntu 批次安裝與測試的 checkbox-satellite project ,其最初的設計似乎並沒有考慮到這些使用情境。與其大規模的重構來符合一個當初設想外的使用情境,或許是發展另外一套解決方案的時候了。

想克服的問題:分開安裝與系統調整兩個動作


我在最初構思新的解決方案的時候,最想解決的問題是 checkbox-satellite 因為奠基於 d-i 的成熟技術所帶來的限制。因為採用 d-i,所以 checkbox-satellite 可以說是不得不將安裝(provisioning)與調整系統(使系統能夠自我自動測試)兩個動作,透過 preseed、early command file 和 late command file 等等好用與成熟的機制高度地綁在一起。好處是這個 preseed 機制在 Debian 和 Ubuntu 社群長久的發展下,功能已經非常穩定、成熟與強大,完全能夠勝任快速開發安裝與調整原生 Ubuntu 的重責大任,缺點則是 checkbox-satellite 當用於非原生 Ubuntu 或是非支援 d-i 機制的 images 時,就要另外發展安裝(provisioning)與調整系統(使系統能夠自我自動測試)兩個動作的需求。

於是我設計了一套基本上是 master-client 式的 client-server model,將 provisioning 和 system configuration 分開,master 只需要分別在不同的階段去觸發這兩個動作、client 只需要針對觸發做回應即可,藉此來 decouple。我很快就意識到這是一個很直覺、所以應該會被大量實做的概念,例如 Puppet[1]、OpenLMI[2]和接下來要聊聊的 Testflinger[3]。

Testflinger 的工作模式:server、agent、cli


Testflinger 很自然地也是採用 master-client 的設計,不過可以再細分為 server、agent 與 cli。定位如下:


  • Testflinger server:負責接收來自 cli 的任務請求、指派任務給 agent 與回收 agent 執行結果。
  • Testflinger agent:負責去認領在 server 上面還沒有被處理的任務。實際與測試目標溝通、執行測試任務、回收測試結果並回報給 server。
  • Testflinger cli:負責觸發任務請求。


所以很自然地,deployment 會像這樣:


  • Testflinger server:裝在某台可以收、送 Restful 通訊機制的 server 即可。該 server 必須要有 Redis server 服務,因為 Testflinger server 透過 Redis 來管理任務佇列。
  • Testflinger agent:裝在某台可以收、送 Restful 通訊機制的機器上即可。通常會設定固定排程讓 agent 定期去 server 上查看有沒有還沒被認領的工作。
  • Testflinger cli:裝在某台可以收、送 Restful 通訊機制的機器上即可。通常是自己的筆電。


因此,所有的測試目標只要是能夠運作 ssh server(或任何其他能夠收到來自 agent 訊息的管道)以及 shell(或是任何其他能夠執行來自 agent 指令的方式)即可。至此 system configuration 的問題已經解決;只要是能夠透過 command line 完成的 configuration,使用這種工作模型,應該都可以滿足。

所以我們只剩下 provisioning 這個問題:那測試目標要怎麼預先準備好 ssh server 和 shell  呢?

使用 MAAS 安裝測試目標


MAAS 提供 bare metal provisioning 的一系列解決方案。因此直接使用 MAAS 將「安裝」這個動作本身,成為一個 Testflinger agent 指派的任務即可。只是 Testflinger agent 驅動的「測試目標」其實變成 MAAS controller,「測試內容」變成「觸發 MAAS controller 去安裝目標機器」。

將 Jenkins 做為 Testflinger cli 觸發來源


從以上討論,其實就暗示了 Testflinger 本質上是「安裝與觸發系統工作」的機制,這套機制如果配合其他的排程機制,基本上就是一套完整的自動化測試解決方案。例如我們可以考慮使用 Jenkins 定期透過 Testflinger cli 發出測試請求、並且回收統整 Testflinger server 的執行結果。




[1] https://docs.puppet.com/puppetserver/latest/services_master_puppetserver.html
[2] http://www.openlmi.org/
[3] 當然還有其他可能的解決方案,例如 Ansible、Chef、Salt 等等。我認為其中最重要的概念是區分自己要做的是「system configuration」還是「application configuration」,而去選擇最適合自己使用情境的。

2017年4月13日 星期四

bluez 與藍牙測試 - 簡介(一)

最近為了大量測試藍牙,稍微評估了一下常見的幾種工具來計畫自動測試的方法。摘要如下。

bluez(protocol stack): Linux kernel 所採納的最新 bluetooth (bt) stack
bluez(debian package): 基於 bluez(protocol stack) 所實做的 daemon 和 tools。

因此透過 dpkg -L bluez 可以知道很多對應的 daemon configuration file 和常用工具有哪些,包括:

顯然是透過 dbus 溝通[1]

/etc/dbus-1/system.d/bluetooth.conf

其中 main.conf 可以調整  discoverable time

/etc/init/bluetooth.conf
/etc/bluetooth/network.conf
/etc/bluetooth/proximity.conf
/etc/bluetooth/input.conf
/etc/bluetooth/main.conf

這裡看起來可以設定自動開啟

/lib/udev/rules.d/50-bluetooth-hci-auto-poweron.rules

常見個一堆工具;我自己比較常用 hciconfig(啟動、調整設備)[2]、hcitool(啟動、調整連線)、bluetoothctl(類似 hcitool, 但是是交互式操作)、obexctl(交互式操作 obex)[3]


/bin/hciconfig
......
/usr/bin/hciattach
/usr/bin/hcitool
/usr/bin/gatttool
/usr/bin/btmon
/usr/bin/l2test
/usr/bin/bluemoon
/usr/bin/ciptool
/usr/bin/bluetoothctl
/usr/bin/l2ping
/usr/bin/rctest
/usr/bin/btmgmt
/usr/bin/hex2hcd
/usr/bin/btattach
/usr/bin/obexctl
/usr/bin/bccmd
/usr/bin/sdptool
/usr/bin/rfcomm

daemon; 如果是使用桌機版,應該一開始開機完進入桌面環境之後就可以查閱這個 daemon 有沒有啟動了(例如 ps aux | grep bluetoothd)

/usr/sbin/bluetoothd


接下來幾篇來寫測試方式和自動化實做。


[1] 有幾次玩到 obexctl 退出的時候,系統抱怨 dbus connection error;應該可以從這裡開始著手除錯。
[2] 別忘了 hci 是 host control interface:用來統一操作 device 的介面;所以 hciconfig 就是「透過 hci 設置、調整藍牙裝置」(hci --> driver --> kernel --> bt device)
[3] object exchange. OBEX is "a communications protocol that facilitates the exchange of binary objects between devices." (wikipedia) 藍牙通訊協議也採納此協議為支援 protocol 的一部分。


distribution: Ubuntu 16.04

2017年3月30日 星期四

使用 QEMU KVM 初探 MAAS - [3] 安裝 MAAS controller


如果上一篇建立虛擬機順利的話,應該可以從你自己的 host machine 連到剛才建立的虛擬機器了。立刻連進去操作(我們可以把 virt-manager 的螢幕關掉沒關係 XD 系統還在背景跑就好,伺服器嘛)(也就是說接下來的頁面都沒圖了 XDD[1]):


└──╼ ssh ubuntu@192.168.101.10
The authenticity of host '192.168.101.10 (192.168.101.10)' can't be established.
ECDSA key fingerprint is SHA256:n1YlztUI2/5EgeVrSNbnmbD1KPEHk1Ud8uOvy0mrkOQ.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.101.10' (ECDSA) to the list of known hosts.
ubuntu@192.168.101.10's password:
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-62-generic x86_64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
42 packages can be updated.
31 updates are security updates.


The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
ubuntu@maas-ctl-01:~$

安裝需要的套件:

sudo apt-get install maas maas-dns maas-dhcp

maas: 主程式
maas-dns: 我們要 maas controller 替我們負責底下 node 的 dns 管理
maas-dhcp: 同 maas-dns,但管理 dhcp

應該就會一口氣裝到可以用[2][3][4]。如果有裝好,這時候你打開你 host machine 的瀏覽器,輸入位置 http://192.168.101.10/MAAS [5],應該要看到下面的畫面:還沒初始化、初次使用的 MAAS cluster 等著你建立第一個使用者。




這介面真是比 1.5 版的時代好看太多了 XDDDDDDDD

[1] 好啦其實還是有一張圖,建議可以先 clone 一份剛裝好的起來,這樣以後要拿去別地方用,或是稍後亂搞搞爛了可以馬上回來,不用重新建立虛擬機,比較省事。




[2] 啊我記得 2015 年剛開始玩 1.5.x 的時候花超多時間去調校的,包括 PostgreSQL語系問題、import boot image etc.,現在這個 2.1.3.x 大概打包和組態設定上已經改善很多了。一口氣到底好過癮喔。

[3] 14.04 搭配的 MAAS 會一口氣弄進很多 boot image ,空間至少要 10GB(後來的 MAAS 版本就可以選要拉哪些 boot image 了);這篇文章是 xenial server。

[4] 14.04 搭配的 MAAS 在拉 boot image 的時候不會顯示下載進度、甚至按下去有沒有反應都不知道(這後來有改掉),可以在 console 輸入  ps aux | grep import 來觀察下載有沒有正常啟動。

[5] 192.168.101.10 是前面文章在建立虛擬機器時指定的 IP,請換成你自己的值。

[6] trouble shooting: 如果 dhcpd 沒有啟動,可能是因為沒有去 subnet 裡面把 maas-dhcp 打開。

使用 QEMU KVM 初探 MAAS - [2] 建立 MAAS server 用的虛擬機


概念上是新增虛擬網路後,在建立虛擬機器的「硬體」組態時可以指定使用該虛擬網路。再基於該組態安裝 MAAS server。



新增虛擬網路


重點兩個:


  • DHCP 要關掉(因為我們要讓 MAAS server 去負責 DHCP,如果這邊也有 DHCP 就會打架)
  • NAT 要透過 host machine 上的實體裝置連外(因為我想要之後碰到網路來更新或是裝其他的東西;如果沒這打算可以不用連外)











這裡我的 gatewat 是 192.168.101.1,這個數字稍後會用到。

安裝 MAAS server

建立虛擬機


virt-manager 的圖形介面很直覺,廢話不多說,截圖幾個關鍵。


用 image 裝


選自己要用的 image [1]


這一步要注意,要選稍早我們建立的 NAT


[1]
安裝的時候要注意 iso 檔案存放位置的存取權限;常見的問題是把 iso 存在另外一個硬碟或是磁區,這會造成  virt-manager 存取的問題。



啟動虛擬機開始安裝 


雖然安裝一開始有提供很多選項,但我自己是偏好裝最基本的,然後再自己去手動裝與調整需要的套件。


我打算做這樣的配置:

MAAS controller: 192.168.101.10
MAAS node 01: 192.168.101.11
MAAS node 02: 192.168.101.12
......
name server and gateway: 192.168.101.1 (兩個都是同一個,往外找 name;注意這個值來自稍早虛擬網路的設定值)


所以這裡給 MAAS controller IP



netmask (因為我要 IP of nodes 像是 192.168.101.xx),所以是 255.255.255.0

稍早提到的 name server and gateway IP


The hostname of this controller

不填 domain name


如果虛擬網路有對外 bridge 成功的話,就會自動偵測到你的時區


中間有些過程就是一般安裝系統會看到的設定,應該滿直覺的,我就略過太細節的部份。

因為是測試機,所以就不更新了;還沒玩過 landscape,有機會再來玩玩。


稍早有提到我喜歡從基本開始裝,所以只選標準套件;因為之後也想要透過 ssh 連進來使用指令操作 MAAS 和 Juju,所以也順手裝一下 ssh server 的功能。


接著就會一路跑到完、安裝好,等著我們做進一步調校囉!請看下一篇:安裝 MAAS controller。

使用 QEMU KVM 初探 MAAS - [1] 安裝 virt-manager

kvm 是個很早就有的概念(1970??),然而在 20?? 左右,有顯著的突破,並且被 Linux 核心所採用。[1]

MAAS 自建雲,然而大多數人都不太有機會輕易蒐集兩台甚至以上的機器,所以虛擬機器自然是一個很直觀的選擇。如果覺得 Virualbox 太吃資源、也用不到太多的硬體模擬的話,可以考慮使用 qemu on kvm,並且透過 virt-manager 來管理。


首先,安裝虛擬機器管理員

sudo apt-get install virt-manager

讀者在安裝完 virt-manager 之後,透過 dash 打開;
第一次打開的時候可能會遇到 virt-manager 抱怨沒有安裝 qemu-system ,
這是正常的[2]

sudo apt-get install qemu-system




安裝完後打開,會被抱怨無法連接到 libvirt




ls -alh /var/run/libvirt/libvirt-sock
srwxrwx--- 1 root libvirtd 0  2月 18 20:37 /var/run/libvirt/libvirt-sock

可以看到 libvirt-sock 是一種 socket 以及錯誤訊息

libvirtError: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied

不用擔心,這時候使用 sudo 給予權限打開就好

sudo virt-manager

如果左上方的 QEMU/KVM 沒有顯示未連結的話,就表示 virt-manager 已經準備好可以使用了。請到下一篇:安裝 MAAS server





* 是說這一系列的文章我在 2015 年初就寫了草稿,那時候還只是 MAAS 1.5.x,現在兩年過去了 2.1.x 都出來了 XDDD ,剛好又回頭要裝一次當除錯環境。因為原本裝好的 trusty 筆電最近炸掉,換成現在在用的 xenial;當時的操作截圖還留在原本的筆電中,一方面懶得救資料、一方面也覺得版本升級了藉機更新一次訊息。這次一口氣發出來這篇 XDD 從草稿上看到很多當時的痕跡,覺得很有意思。

2017年2月5日 星期日

paraview python macro

paraview 是一套強大的、可用於呈現 VTK 系列檔案[1]的工具,同時也是由 Kitware 公司維護的 open source software。

通常操作 paraview 的流程是:啟動 GUI、讀入檔案[2]、選擇要呈現的屬性[3]、操作 camera 來檢視圖形、播放隨時間流逝的動畫(需要讀入數個檔案,見[2])。

在 CFD 開發與實驗的過程中,如果每次產生的資料與數據,都要手動調整 GUI (例如上述的步驟)來檢查每次的結果,是非常沒有效率的事情。paraview 有提供接口,讓使用者可以透過 python 來操作 paraview 引擎;因此使用者可以撰寫 python macro 來簡化每次的操作。

安裝


Ubuntu 可以透過安裝 paraview-python 套件來取得 python 支援。

使用


參考 paraview wiki,或是 paraview 本身的 document 都很不錯。

tips - 好用的 trace


paraview 本身有提供「記錄使用者操作的流程,然後直接輸出成 python macro 」的超級好用功能。這樣使用者可以很直觀地操作之後(例如轉動物體到自己看得順眼的角度),直接取得 python script (欸欸欸這樣認真 K 上面 document 或是 wiki 的人情何以堪 XD)。

使用上就從 GUI 選擇 Tools 列表中的 Start Trace 選項,然後開始操作 paraview GUI[4]。操作完畢後選擇 Stop Trace ,並且存檔取得 python script。這樣就大功告成了。非常方便的功能!

理解 paraview python script


paraview 的運作邏輯大致上如下:


  • 資料 IO 、讀入檔案(注意支援一次讀多個檔案),用 reader 物件代表讀入結果。
  • Show:產生即將要呈現的資料的圖形屬性管理者 display
  • Render:渲染、呈現 display。包括動畫的部份。
  • Camera:決定使用者的視角(所以旋轉圖形什麼的由這裡操作)

由 paraview.simple module 提供操作層。(注意不是 module paraview;module paraview 應該是引擎本身)


資料讀入


  • OpenDataFile (泛用的方法,會自己判定是哪種 grid 幾何)
  • XMLUnstructuredGridReader、xxxxReader (直接指定 reader,注意可以透過 Filename keyword 來傳入檔案 list)



[1] 一種檔案格式,有多種延伸格式(例如 vtu)。常用於呈現 3D 幾何圖形,廣泛在地球科學與計算流體力學中被採用。特色之一是支援平行化運算。
[2] paraview 支援一次讀入檔名連續的不同檔案,常用於顯示不同時間的圖形幾何。
[3] 通常是用來呈現物理意義上的屬性。由檔案寫入者決定任何的 attribute 名稱。例如可以是壓力或者溫度。
[4] 你可能會遇到需要 python-pygments 套件的問題;Ubuntu 上透過 apt 安裝該套件可以解決這個問題。

2017年1月18日 星期三

diff 工具中的 unified format

稍早在討論 cram 這個測試工具的文章中[1],有提到 unified format。這邊文章稍微補充一些更多的香關知識。動機很單純,因為 diff 這個實用的工具用很久了,順便整理一下對於新接觸這種格式的人可能會有的障礙。wikipedia 上面其實已經整理得很清楚了[2],這邊算是中文摘要。

[1] http://zh-tw-tai271828.blogspot.tw/2017/01/cram.html
[2] https://en.wikipedia.org/wiki/Diff_utility#Unified_format

unified format

最主要是要知道要怎麼解讀這個格式

@@ -l,s +l,s @@ optional section heading


  • 格式開頭由兩個 @包夾
  • - 原本的檔案
  • + 更動後的檔案
  • l 開始的行數
  • s 由開始起算的相關行數(刪減、更動或是增加)

簡史


Wayne Davison 在 1990 八月提出,隨後由 Richard Stallman 加入 GNU diff 中 (GNU diff 1.15)

字彙



  • hunk - 在這裡指「一整個更動過的文字區塊」。了解這個字義有助於使用 patch 時,可以更清楚地解讀上 patch 後 patch 工具所反饋的訊息。

初探命令列測試工具 cram

cram 簡介


cram 是一個設計來適用於測試命令列的工具。包括下面特性

  • 執行一個 .t extention file 來進行測試
  • 測試結果使用 unified format[1] 呈現

我的心得是似乎是一個可以用於 function test or API test 的工具:測試產品整體的執行結果。[2] 另外就是近年來似乎使用 command pattern + factory pattern 的命令列實作似乎越來越常見[3],或許是一個值得了解的測試方式。


[1] https://en.wikipedia.org/wiki/Diff_utility#Unified_format
[2] 請見下面的「mercurial 的測試設計思想」
[3] kubernetes, mercurial, MAAS, checkbox(這個不完全是,沒有前面三者這麼"API")

使用範例


安裝
pip install cram

取得 cram source code (我只是要拿裡面 cram 測試自己 source code 的 test file)
git clone git@github.com:brodie/cram.git

進到取得的 source code 中存放  test file 之處
cd <cram source root>/cram/tests

執行看看
cram usage.t

稍微改動一下 usage.t,比較一下前後輸入輸出結果,大概就會有些感覺了。包括:

  • .t file 基本上由兩者構成:「要執行的命令」、「執行後的輸出」
  • 由空白兩行的縮排來告知 cram 「這是要執行的命令與執行後的輸出」

已經有過的討論案例:mercurial 的測試設計思想


在研究 cram 的過程中,我發現了這個討論串[1][2],大致上是說
  • mercurial 的開發上,產品的測試佔極大部份(程式碼幾乎是產品本身行數的一半),unit test 只有一點點
  • 上面這種測試的中心思想是「我只保證 API 行為始終一致,中間怎麼實作基本上你不要管我」。優點是向下相容容易、測試程式碼不需要跟著一直改動。
  • 有人就建議那這樣可能適合使用 cram[3]
[1] https://www.selenic.com/blog/?p=663
[2] https://www.selenic.com/blog/?p=582
[3] 我不知道最後 mercurial 最後有沒有採取這個作法,有興趣可以追一下。cram 的開發好像也沈寂了一段時間了就是。(cram 在 github 上面的 README 中,有些 link 還是指到 bitbucket 上呢)

自己想用上的案例:SOLVCON 上面使用 cram


動機


在 2015 的計畫中(對滿一年了 XD),我們有考慮設計 mesh IO 的 API。目前 mesh 工具也是朝著 command + factory pattern 的方式實作。

可以預期的問題


  • 有些行為本質是亂數,例如切  partition 的方式
  • elapsed time 資訊不太可能每次一樣
所以至少第一步是要先挑出究竟哪些 mesh/block 行為並不會改變,再去實作。








2017年1月17日 星期二

書摘:Effective Debugging - Item 21 修正所有造成問題的類別實例

這也是很直觀,不過作者舉了一些找出類似實例的方式,例如


  • 用 grep 找出關鍵字、使用 -v [1] 做過濾、使用 --color=always 高亮自己要的訊息
  • sort -u 移除重複
在某些情況下,例如使用不推薦或是錯誤的 API,可以使用 global include file 來重新定義錯誤的 API 名稱,讓他改作其他事情(例如拋出警告取代實際執行),這樣就可以在程式早期(例如編譯或是連結的時候)就發現問題了。

[1] 我自己 -v 也是用很兇,在這裡看到有同好也是,覺得安心 XDDDD

書摘:Effective Debugging - Item 20 除錯前後理清資訊

debugging 是一個在複雜的環境中找線索的過程,起頭往往可以是(部份舉例)


  • 能夠協助你找到問題的工具是什麼?
  • warnings 訊息等等是什麼?
  • 好像跟你的問題有關的、但你又讀不懂的程式碼段
  • comment 有些關鍵字例如 "should" "think" "must" "FIXME" "TODO" 等等的程式碼附近。
關掉或是移除這些嫌疑犯(例如會產生 warning 的程式碼片段)來找出錯誤;注意因為可能性太多了,所以務必要在除錯之前,把要除錯系統先「穩定」下來;除非你真的很確定有幫助,不然不要貿然升級或是改動程式碼等等。

除錯完成後,記得
  • 在程式裡面尋找類似的錯誤
  • 加入可以在未來協助找出類似錯誤的例外處理 [1]
  • undo 任何暫時性的修改(可以考慮搭配 version control)


[1] 這點對我而言有被刺激到,例如我後來就在 SOLVCON 裡面加入了類似的檢查,來找出未來 boundary condition 是一個 generic layer 而不是具體的 boundary condition 時,拋出訊息。https://github.com/solvcon/solvcon/pull/180/commits/d946c3d1b6bb23d9011f0f774cf9c2c917848579

書摘:Effective Debugging - Item 19 自動化除錯任務

這其實滿直觀的一種想法:把針對某個任務常用到的指令整合、寫下等等方便重複利用,或是反覆替自己找出有用的資訊。這章節的價值在於作者很具體地提供某些工具的名稱和應用方式。例如:


  • which 很慢,如何分析自己的 PATH 變數(搭配 sed, pipe and while),找出 typo
作者另外指出各種怪現象都有對應的工具(並且列出書中對應章節供更進一步的參考),例如:
  • API violations
  • memory butter overflows
  • race conditions

我自己是有一個心得,使用編輯器的 exhaustive search 之前,可以先大概想一下,自己遇到的這個案例,適合這樣做,或是適合先寫個 script 來幫你過濾程式碼或是 log。

總之如作者所說:「computer time is cheap, yours is expensive.」(我個人是覺得把 time 換成專注力,應該更貼切)

書摘:Effective Debugging - Item 18 從你的桌面替其他不便的系統除錯

不是自己平常使用的系統當然很不習慣,例如缺少某些自己慣用的工具,這個章節提供幾個方法讓想要除錯的系統盡可能地接近自己習慣的環境。


  • 對於手機 app 或是有些 embedded devices,使用 device emulator;這樣就可以使用自己習慣的螢幕、鍵盤和編輯器。缺點是可能無法使用 symbolic debugger。
  • 搭配 device emulator,使用 shim 這種技巧的概念:使用一個中介(例如檔案 IO),來存放執行時相關的資料或是參數,實際的 code 則是跑在本機。本技巧通常只是用演算法測試,不包括 UI 測試。我自己是覺得 core.dump 就是類似的東西。書中是舉手機中某個會用到網路與 API 的應用程式先在本機上寫好並且測試好,然後包成一個 class 整合進去原本的程式碼。
  • Teamviewer 這東東應該不用再多說明了,名氣響亮。
  • Teamviewer + strace or truss command on a third-party computer.
  • KVM over IP device;使用情境:inaccessible data center. 我自己有用過這種東西(使用跟架設都有),有點厲害。例如,自己桌機的鍵盤訊號可以透過網路,在遠端的機器上就像真實的鍵盤輸入一樣(螢幕輸出則是由遠端電器訊號忠實送到你面前)。這種物理手段可以作到連 BIOS 階段都可以進去、調整。只是因為訊號傳送要一段時間,所以想要進 BIOS 有點要透過盲按 XDD 因為 BIOS 畫面往往幾秒而已,等送到你的螢幕上時早就跳掉了。


2017年1月9日 星期一

修 hot key 實例 (Ubuntu Yakkety on Dell Latitude 7370)

今天在 Launchpad 上看到有人回報筆電 Dell Latitude 7370 麥克風靜音 hotkey (Fn + F4)無效(LP:# 1654827)[1]。這個回報很有意思,顯然回報者是一位專業玩家,他的回報非常具體、提供的資訊在除錯上非常地有用,很適合做為一個小小的教學範例;因此動了念頭想介紹一下這個範例。

原因

hwdb 中原本預期的 event value 150,在 driver 中給出的值是 100150。[2]

會使用到的工具


  • acpi_listen
  • showkey
  • evtest
  • systemd-hwdb https://www.freedesktop.org/software/systemd/man/systemd-hwdb.html#

需要的背景知識



  • hwdb 經由 systemd-hwdb 這個指令會編譯成 binary (叫做 hwdb.bin),提供給  wmi 這個 module 使用。
  • hwdb https://www.freedesktop.org/software/systemd/man/hwdb.html
  • wmi https://wiki.ubuntu.com/Kernel/Reference/WMI

[1] https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1654827
[2] https://github.com/systemd/systemd/pull/5012


2017年1月3日 星期二

Mesa 和 Linux graphic stack 簡介

前陣子提到 PRIME 技術,今天把更多相關知識補齊。

以下大多是從[1]這篇文章所做的摘要。

graphic stack 的「演化」


  • 2D: 透過 X server 來控制硬體(螢幕上畫圖等,rendering)。參考下面的「X window 架構」
  • 3D: 使用 OpenGL 實作的應用程式透過 X server 來控制硬體、rendering。這叫 indirect rendering (相對於 direct rendering 的一個詞彙)。參考下面的 「GLX 架構」
  • 3D + DRI (Direct Rendering Infrastructure): 使用 OpenGL 實作的應用程式透過 X server 來控制硬體、rendering。

X window 架構


  • X client 控制資料運算、X server 控制硬體。(注意一台 ssh server 是透過 X client 和某處的 X server 溝通,不要混淆了一般的 server 詞彙涵義和 X server 的「server」)
  • X client 透過 X11 protocol 和 X server 溝通,實作是 Xlib。
  • X server 透過 DDX (device-dependent X) driver 和硬體溝通。


GLX 架構 / Indirecting Rendering


  • Hardware --> OpenGL --> OpenGL API --> libGL.so--> OpenGL application,但這條路在中間還有 X server 的時候會不通,因此用 GLX 來串連。
  • OpenGL application --> GLX --> X server --> GLX driver --> kernel
  • 效率會因為多一層要通過 X server 就會比較差,因此有 DRI 架構

DRI 架構

  • 上面的 in-directing rendering 效率較差,因此試試 directing rendering
  • Hardware --> kernel (DRM) --> OpenGL DRI driver --> OpenGL / libGL.so --> OpenGL application
  • DRM 可以說是 DRI 在 kernel 面向的實作,包括有給 userspace 呼叫的 API

MESA


有了上面的概念之後,就可以理解 Mesa 在 graphic stack 中扮演的角色了。Mesa 包括:
  • 包/利用 libGL
  • 基於 DRI/DRM 架構
  • Mesa 面向的 GLX;原則上還是讓 X 去控制原本 X server 已經在控制的東西,例如圖形內容;Mesa 本身只是想要同步好 X server 已經在控制的內容和透過 DRI 進出的資料與運算。





[1] https://blogs.igalia.com/itoral/2014/07/