2018年11月22日 星期四

修改 Ubuntu 18.10 Cosmic Cuttlefish 中 live system 的 initial ramdisk


拜了一下 google 好像沒人問過;如果有人想要修改最新釋出版本 Ubuntu 18.10 Cosmic Cuttlefish 中 live system 的 initial ramdisk 的話,因為打包 initrd 的內容和格式和以往的釋出版本不一樣,我整理了一下解開 initrd 和修改後重新打包的方式供大家參考和賜教,希望會有幫助。

https://askubuntu.com/questions/1094854/how-to-modify-initrd-initial-ramdisk-of-ubuntu-18-10-cosmic-cuttlefish/1094855




本文同步刊登於 https://www.facebook.com/groups/ubuntu.zh.hant/permalink/2339936602728315/

2018年8月7日 星期二

讓 matplotlib 和 seaborn 支援中文


核心概念:


  • 支援中文其實就是想辦法讓系統支援 CJK 字型;所以本質上是「換字型」的方法。用 "customized font" 當關鍵字下去找,會比「中文 支援 matplotlib」的資料豐富。
  • 想辦法讓 matplotlib 有對應的 CJK 字型、並且在畫圖的時候找得到那些字型
  • matplotlib 可以說是 seaborn 的底層元件



所以實做上會是:

  • 確認系統某處有中文字型,或是怎麼準備需要的字型檔案。
    • matplotlib 吃 ttf
    • 指令 fc-list :lang=zh or fc-cache -fv
  • 搞清楚 matplotlib 要讀的字型要放哪裡
  • 搞清楚 matplotlib 可以怎麼讀
  • 討清楚 matplotlib 讀到的字型,可能是怎麼傳遞給 seaborn


查看系統中字型


查看字型(限 zh)
fc-list :lang=zh

查看字型快取
fc-cache -fv

查看 matplotlib 讀得到的字型


from matplotlib.font_manager import FontManager
import subprocess
fm = FontManager()
mat_fonts = set(f.name for f in fm.ttflist)
可以參考這個 gist




存放 matplotlib 讀得到的字型的地方


/usr/share/fonts/truetype/arphic

或是

site-packages/matplotlib/mpl-data/fonts/ttf

因為吃 ttf,而現在很多字型已經是 ttc 這種格式(把好幾個 ttf 打包起來),所以可以將系統中的中文字型抽出來放進上述目錄裡。這支小程式可以幫忙做這種轉檔





讓 matplotlib 開始讀字型


注意,每一次的新增刪減字型,都要把快取移除,新的狀態才會生效

rm -fr ~/.cache/matplotlib

每一次使用的時候決定要使用的字型

new_fonts = ['AR PL UKai TW'] + mpl.rcParams['font.sans-serif']
mpl.rcParams['font.sans-serif'] = new_fonts

或是可以調整 site-packages/matplotlib/mpl-data/matplotlibrc 來選定每次的預設字型(沒有好好試過)


seaborn 上的字型


對 seaborn 操作後,matplotlib 字型設定會回到預設值。要再調整過。










Ref:

https://newtoypia.blogspot.com/2018/08/matplotlib-ttc.html

https://scentellegher.github.io/visualization/2018/05/02/custom-fonts-matplotlib.html

https://monkey0105.github.io/2016/10/10/matplotlib-chinese-display/

https://medium.com/@aitmr1234567890/%E8%A7%A3%E6%B1%BApython-3-matplotlib%E8%88%87seaborn%E8%A6%96%E8%A6%BA%E5%8C%96%E5%A5%97%E4%BB%B6%E4%B8%AD%E6%96%87%E9%A1%AF%E7%A4%BA%E5%95%8F%E9%A1%8C-f7b3773a889b

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 打開。