跳到主要內容

Apply DriverDisk on RHEL/CentOS6

Problem

在系統自動安裝部屬時,可能有以下原因需要更新驅動:

  1. 安裝光碟搭載的kernel版本不支援新硬體。
  2. 安裝光碟搭載的kernel版本過舊。

最常遇到的問題,莫過於在更新網卡或磁碟陣列驅動了。如果使用kickstart自動部屬,在發生硬體找不到時,應會出現如下圖錯誤:

本篇主要分享我解決此問題的方法,有以下幾個步驟:

  1. 準備driver rpm。
  2. 製作driverdisk。
  3. 指定driverdisk。
  4. 調整kickstart檔案。

準備driver rpm

準備rpm目前我試了兩種方法:

  1. 直接透過rpmbuild打包Intel下載的驅動包。
  2. 自行撰寫rpm spec檔案去產生rpm檔。

透過Intel驅動包產生rpm

最初使用這方法產生的rpm包裝driverdisk,卻發現一直無法正常載入:

在使用方法二與檢查driverdisk程式碼後,發現原因主要有二:

  1. kernel-modules版本的判別: .spec的Providers宣告不滿足需求,參考程式碼linklink
  2. kernel-modules檔案的副檔名: 檔名需為.ko,參考程式碼link

因此針對Intel驅動包內的.sepc,我做了以下修改(以ixgbe驅動為例):

# 原本為Provides: %{name},修改為以下
Provides: kernel-modules >= 2.6.32-220
 
# 原本為將ixgbe.ko改名為ixgbe.ko.new,我改為複製並放入檔案清單中
find lib -name "ixgbe.*o" -exec cp {} {}.new \; \
         -fprintf %{_builddir}/%{name}-%{version}/file.list "/%p.new\n/%p\n"

修改後再重新產生的rpm與driverdisk就能夠正常載入驅動。

自行撰寫rpm spec去產生rpm

一開始使用方法一失敗後,並沒足夠時間追究原因,後來是學網路上教學自己寫。

製作driverdisk

我所產生的driverdisk,以iso為主;driverdisk的內容,會長這樣:

rhdd3
rpms/
rpms/x86_64
rpms/x86_64/ixgbe-4.3.15-1.el6.x86_64.rpm
rpms/x86_64/repodata
rpms/x86_64/repodata/0521246c6369e8276fa1f75fa71187e6e81d1009551529a7f0ca97846e2ec278-primary.xml.gz
rpms/x86_64/repodata/32927a3988d99cbfaa3f710208c326b544154adab3a01510e90649b03e6b2a88-other.sqlite.bz2
rpms/x86_64/repodata/8222113261bc634eb8373e6c036e7f3ff2081607836c9818372dd43be048dbc6-other.xml.gz
rpms/x86_64/repodata/a81432fe5d910a52559ed3f66b0b89a8b21b45fd1cf6d80a227fe77f0932c29e-filelists.sqlite.bz2
rpms/x86_64/repodata/b94224988823cc79f0a28e8d2ace4fe6f7d58c2d2f86e138b69858632825421e-primary.sqlite.bz2
rpms/x86_64/repodata/caee3a920c6960f597ebb405912500080b18c83b804f2e00f81f6a2e661537f8-filelists.xml.gz
rpms/x86_64/repodata/repomd.xml

在使用上有兩個種類

  1. 讀立的driverdisk。
  2. 與安裝光碟包一起。

讀立的driverdisk

假如你是獨立的driverdisk,可以透過此連結所提供的腳本,輸入rpm並產生iso:

./mkdriverdisk.sh ixgbe-4.3.15-1.el6.x86_64.rpm

與安裝光碟包一起

假如你想要與安裝光碟包一起,有幾個步驟要做:

  1. 解開iso。
  2. 在光碟根目錄產生rhdd3檔案,內容隨便給。
  3. 在光碟根目錄產生rpms/x86_64資料夾,並將rpm給丟進去。
  4. 到rpms/x86_64目錄中,執行createrepo -p -d ./,就會產生repodata。
  5. 重新打包iso。

你也可以選擇將mkdriverdisk.sh產生的iso解開後,丟到安裝光碟的iso中。至於解開iso與打包iso,要自行去網路上找方法,非本篇重點。

指定driverdisk

從driverdisk程式碼中可以得知,可以使用nfs、ftp、http存取driverdisk。但如果你需要的是載入網卡驅動呢? 因此我是在boot參數中,加入dd或driverdisk:

default linux ksdevice=link ip=dhcp loglevel=debug ks=cdrom:/ks.cfg dd=path:/dev/sr0

如果你在有兩台光碟機以上的機器,必須明確知道是使用sr0或sr1;也許你會問,那怎不用dd=cdrom呢? 這我也試過,會出現以下訊息等待確認:

還有另外一個方式是在kickstart answer file中設定driverdisk位置:

driverdisk --source=path:/dev/sr0

比起修改boot config內容,使用answer file的方式比較有彈性。

調整kickstart檔案

在通過no driver found後,接著很可能會出現以下錯誤:

雖然透過ifconfig可以看到網卡已找到,但檢查syslog會發現找不到網卡設定檔:
這錯誤會在執行kickstart安裝動作前,因此你可以在%pre區塊中,去產生預設的設定檔:

network_devices=($(ls -I lo /sys/class/net));
for device in ${network_devices[@]};
do
	config=/etc/sysconfig/network-scripts/ifcfg-$device
	if [ ! -e "$config" ];
	then
		logger "$device config doesn't exist! Setup $device config."
		cat << EOF > "$config"
BOOTPROTO="dhcp"
DEVICE="${device}"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
ONBOOT="yes"
EOF
	fi
fi

而在安裝完成重新啟動後,你可能就會遇到更新後的驅動沒被載入的問題。針對載入網卡驅動的問題,網路上有些做法;首先是編輯modprobe conf,在你知道有幾張網卡的前提下,你可以在/etc/modprobe.d/anaconda.conf中加入類似以下內容:

alias eth0 ixgbe
alias eth1 ixgbe

假如你不管網卡名稱或數量,你也不曉得更新的模組是不是網卡,另外一個選擇是新增/etc/sysconfig/modules/anaconda.modules檔案,在裡面載入那些ko檔:

#!/bin/sh
/sbin/modprobe ixgbe

然而在使用第二個方法時,我又想到一些問題:

  1. 不同版本驅動可能會不同位置,我要去覆蓋掉原本的嗎?
  2. 假如新的驅動在原本的系統就不存在,使用modprobe不會有問題嗎?

我認為應交由kernel本身自行去判別驅動狀態,包含驅動相依性;因此我透過了depmod指令,讓系統自行去判別目前kernel modules狀態。我在answer file中,加入一個post區塊,並讓它在chroot下去執行depmod:

%post
DD=/root/DD
if [ -e "${DD}" ]; then
	logger "setup update drivers"
	cp -r ${DD}/lib/* /lib
	/sbin/depmod -r
fi
%end

按照以上流程,就能夠更新驅動並安裝完成系統。這部分試驗過ko來源與原本相同與不同兩種案例,都可以正常使用到最新版本驅動。

其它

我的測試環境是在CentOS6.6上。為了方便建置測試環境,撰寫了以下腳本。

#!/bin/bash
REPO_URL=http://archive.kernel.org/centos-vault/6.6/os/x86_64/Packages/
KERNEL_DEVEL=kernel-devel-2.6.32-504.el6.x86_64.rpm 
KERNEL_HEADERS=kernel-headers-2.6.32-504.el6.x86_64.rpm
 
mkdir /opt/rpms
cd /opt/rpms
 
yes | yum -y install wget
 
wget ${REPO_URL}${KERNEL_DEVEL}
wget ${REPO_URL}${KERNEL_HEADERS}
 
#yum -y remove kernel-devel
#yum -y remove kernel-headers
 
rpm -ivh *.rpm
 
yum -y install rpm-build gcc createrepo mkisofs

Reference

留言

這個網誌中的熱門文章

Show NIC selection when setting the network command with the device option

 Problem  在answer file中設定網卡名稱後,安裝時會停在以下畫面: 所使用的command參數如下: network --onboot = yes --bootproto =dhcp --ipv6 =auto --device =eth1 Diagnostic Result 這樣的參數,以前試驗過是可以安裝完成的。因此在發生這個問題後,我檢查了它的debug console: 從console得知,eth1可能是沒有連接網路線或者是網路太慢而導致的問題。後來和Ivy再三確認,有問題的是有接網路線的網卡,且問題是發生在activate階段: Solution 我想既然有retry應該就有次數或者timeout限制,因此發現在Anaconda的說明文件中( link ),有提到dhcptimeout這個boot參數。看了一些人的使用範例,應該是可以直接串在isolinux.cfg中,如下: default linux ksdevice = link ip =dhcp ks =cdrom: / ks.cfg dhcptimeout = 90 然而我在RHEL/CentOS 6.7與6.8試驗後都無效。 因此我就拿了顯示的錯誤字串,問問Google大師,想找一下Anaconda source code來看一下。最後找到別人根據Anaconda code修改的版本: link ,關鍵在於setupIfaceStruct函式中的setupIfaceStruct與readNetConfig: setupIfaceStruct: 會在dhcp時設定dhcptimeout。 readNetConfig: 在writeEnabledNetInfo將timeout寫入dhclient config中;在wait_for_iface_activation內會根據timeout做retry。 再來從log與code可以得知,它讀取的檔案是answer file而不是boot command line。因此我接下來的測試,就是在answer file的network command上加入dhcptimeout: network --onboot = yes --bootproto =dhcp --ipv6 =auto --device =eth1 --dhcptimeo

解決RobotFramework從3.1.2升級到3.2.2之後,Choose File突然會整個Hand住的問題

考慮到自動測試環境的維護,我們很久以前就使用java去執行robot framework。前陣子開始處理從3.1.2升級到3.2.2的事情,主要先把明確的runtime語法錯誤與deprecate item處理好,這部分內容可以參考: link 。 直到最近才發現,透過SeleniumLibrary執行Choose File去上傳檔案的動作,會導致測試案例timeout。本篇文章主要分享心路歷程與解決方法,我也送了一條issue給robot framework: link 。 我的環境如下: RobotFramework: 3.2.2 Selenium: 3.141.0 SeleniumLibrary: 3.3.1 Remote Selenium Version: selenium-server-standalone-3.141.59 首先並非所有Choose File的動作都會hang住,有些測試案例是可以執行的,但是上傳一個作業系統ISO檔案一定會發生問題。後來我透過wireshark去比對新舊版本的上傳動作,因為我使用 Remote Selenium ,所以Selenium會先把檔案透過REST API發送到Remote Selenium Server上。從下圖我們可以發現,在3.2.2的最後一個TCP封包,比3.1.2大概少了500個bytes。 於是就開始了我trace code之路。包含SeleniumLibrary產生要送給Remote Selenium Server的request內容,還有HTTP Content-Length的計算,我都確認過沒有問題。 最後發現問題是出在socket API的使用上,就是下圖的這支code: 最後發現可能因為開始使用nio的方式送資料,但沒處理到尚未送完的資料內容,而導致發生問題。加一個loop去做計算就可以解決了。 最後我有把解法提供給robot framework官方,在他們出新的版本之前,我是將改完的_socket.py放在我們自己的Lib底下,好讓我們測試可以正常進行。(shutil.py應該也是為了解某個bug而產生的樣子..)

PostgreSQL - Unattended installation on windows

Introduction 要將別人軟體包裝到自己軟體中,不可或缺的東西就是Unattended installation。以Unattended installation來說,我們可以選擇透過Installer的silent mode安裝,也可以透過把目標軟體做成portable的版本。本篇文章分享這兩種方法,教導大家如何將PostgreSQL透過Unattended installation方式安裝到目標系統成為service。 Note. 本篇以PostgreSQL 10.7為例。 Install with installer Tips 安裝程式或反安裝程式的參數,除了可以直接上官網搜尋Installation User Guide以外,也可以直接使用help參數查詢: postgresql- 10.7 - 2 -windows-x64.exe --help Windows安裝程式主要有EnterpriseDB與BigSQL兩種。BigSQL版本安裝元件是透過網路下載且支援參數不如EnterpriseDB版本多,以我們需求來說,我們傾向於使用EnterpriseDB版本。接下來分享給大家安裝與反安裝方法。 Installation @ echo off set INSTALL_DIR =C:\postgres10 set INSTALLER =postgresql- 10.7 - 2 -windows-x64.exe   rem options for installation set SSMDB_SERVICE =postgresql- 10 set MODE =--unattendedmodeui none --mode unattended   set DB_PASSWD =--superpassword postgres set DB_PORT =--serverport 5432   set SERVICE_NAME =--servicename % SSMDB_SERVICE %   set PREFIX =--prefix "%INSTALL_DIR%" set DATA_DIR =--datadir "%INSTALL_DIR%\data"   set OPTIONS =