利用 UNIX 腳本來(lái)管理 DS4000 磁盤(pán)陣列系統(tǒng)
為什么使用 Unix 腳本來(lái)管理 DS4000
作為一個(gè)測(cè)試工程師,在我的日常工作中我經(jīng)常要花費(fèi)大量的時(shí)間去完成一些很簡(jiǎn)單但是很耗時(shí)的工作。例如,一次我想在 DS4000 上創(chuàng)建 200 個(gè)磁盤(pán)。但是由于 DS4000 沒(méi)有能夠批量創(chuàng)建磁盤(pán)的功能,我花費(fèi)了 4 個(gè)小時(shí)一個(gè)一個(gè)地去創(chuàng)建。這次的經(jīng)歷使我有一種想法去創(chuàng)建一個(gè)能夠可以批量地創(chuàng)建磁盤(pán)的工具。經(jīng)過(guò)我一段時(shí)間的研究,我發(fā)現(xiàn) IBM Storage Manager 支持 CLI(Command Line Interface)功能,這就意味著我可以利用 UNIX 系統(tǒng)的腳本功能來(lái)創(chuàng)建一個(gè)可以被 IBM Storage Manager 使用的腳本。通過(guò)在 IBM Storage Manager 運(yùn)行這個(gè)被創(chuàng)建的腳本,可以在無(wú)需人機(jī)交互的情況下批量的創(chuàng)建磁盤(pán)。但是作者并不保證本方法在任何情況下總是可以成功,請(qǐng)讀者在驗(yàn)證本文的例子時(shí)注意做好相應(yīng)的備份,最好在實(shí)驗(yàn)環(huán)境上進(jìn)行操作。
例子腳本介紹
那么如何創(chuàng)建 IBM Storage Manager 可使用的腳本呢?IBM Storage Manager 有它自己的腳本格式。只有腳本的變量值改變而格式并不改變。所以,UNIX 腳本需要能夠讓用戶能夠定制的輸入自己的所對(duì)應(yīng)的值,如需要?jiǎng)?chuàng)建磁盤(pán)的數(shù)量,HBA 卡的 WWPNs 值,來(lái)生成 IBM Storage Manager 能夠使用的腳本文件。可以設(shè)計(jì)一個(gè)配置文件來(lái)讓用戶輸入自己對(duì)應(yīng)的變量值。下面就是個(gè)配置文件的例子:LunNumber:30 #30 個(gè) LUNsArrayNumber:1 # 這些 LUNs 創(chuàng)建在 array 1 上LunName:sunx325b # 這些 LUNs 的名字將為 sunx325b_0, sunx325b_1 ...Capacity:0.5GB # 每個(gè) LUNs 的容量是 0.5GBHostGroupName:sunx325b_group # 這個(gè)主機(jī)組的名字為 sunx325b_groupHostName:sunx325b # 這個(gè)主機(jī)名為 sunx325bPort0:210000e08b0e934d # 第一個(gè) HBA 卡的 wwpn 值Port1:210000e08b0e6e50 # 第二個(gè) HBA 卡的 wwpn 值HostType:8 # 主機(jī)類型
完成了對(duì)配置文件的定義以后,Unix 腳本可以把配置文件中用戶定義的值解析出來(lái),并且組織成為 IBM Storage Manager 可以使用的腳本。一個(gè)比較好的解析配置文件的工具是 SED 編輯器,這是一個(gè)流式的編輯器。SED 編輯器將需要處理的文本作為輸入,經(jīng)過(guò)一系列操作以后,輸出經(jīng)過(guò)修改的文本。SED 編輯器的典型應(yīng)用就是通過(guò)模式的匹配來(lái)提取文件中的一部分內(nèi)容或者是把文件中的多個(gè)相同的字符串進(jìn)行替換。UNIX 腳本可以通過(guò)使用 SED 編輯器從配置文件中得到需要的數(shù)值,并把這些值添加到能夠被 IBM Storage Manager 使用的腳本中去。
例如,下面展示了如何使用 UNIX 腳本從配置文件中獲取磁盤(pán)數(shù)量這個(gè)值。這個(gè)腳本從配置文件獲取 LunNumber 這個(gè)值,然后把這個(gè)值賦給腳本中的對(duì)應(yīng)變量 LunNumber。sed -n '/LunNumber:/'p $ConfigFile >tmplunNumber=`sed 's/LunNumber://' tmp`
例子腳本的詳細(xì)說(shuō)明
下面的例子是展示如何使用 SED 編輯器生成一個(gè) IBM Storage Manager 可以使用的腳本。這個(gè)例子中,腳本從配置文件中獲得了 ArrayNumber,LunName 和 Capacity 的值,用于生成 IBM Storage Manager 使用的生成磁盤(pán)的命令,然后把這個(gè)命令添加到 IBM Storage Manager 的腳本(crtlun.cmd)文件。x=0while [ $x -lt $lunNumber ]doy=`expr $x % 2`if [ $y -eq 0 ]thenecho "create logicalDrive array=$arrayNumber userLabel="${lunName}_${x}"capacity=$capacity owner=a;" >> crtlun.cmdelseecho "create logicalDrive array=$arrayNumber userLabel="${lunName}_${x}"capacity=$capacity owner=b;" >> crtlun.cmdfix=`expr $x + 1`done
這個(gè) Unix 工具的內(nèi)容是不是很簡(jiǎn)單?但是它卻幫助了我把原來(lái)需要幾個(gè)小時(shí)的工作減少為只需要幾分鐘就可以完成。下面讓我對(duì)我的 UNIX 腳本文件的內(nèi)容做個(gè)比較詳細(xì)的介紹。這個(gè)名字為 ds4kscript.sh 的腳本文件可以運(yùn)行在 UNIX(AIX,Solaris,Linux 等)上,用于產(chǎn)生一個(gè)可以在 IBM Storage Manager 上運(yùn)行的腳本。它可以用于在 DS4000 系列上創(chuàng)建和刪除 Lun、host group、host、host port,映射 Lun 等功能。
這個(gè)腳本的輸入是配置文件:config。它保存這用戶自定義的配置信息。這個(gè)腳本的輸出是一系列的腳本(這個(gè)功能在后面會(huì)加以介紹):crtlun.cmd, crthost.cmd, maplun.cmd, delmap.cmd, delhost.cmd, dellun.cmd, setup.cmd, destroy.cmd 支持的操作系統(tǒng):AIX,Solaris 和 Linux
腳本使用說(shuō)明
編輯 config 文件,設(shè)置參數(shù)為用戶所需要的值。下面是一個(gè)例子,顯示了 config 文件需要包含那些項(xiàng)以及一些說(shuō)明:LunNumber:30 #30 個(gè) LUNsArrayNumber:1 # 這些 LUNs 創(chuàng)建在 array 1 上LunName:sunx325b # 這些 LUNs 的名字將為 sunx325b_0, sunx325b_1 ...Capacity:0.5GB # 每個(gè) LUNs 的容量是 0.5GBHostGroupName:sunx325b_group # 這個(gè)主機(jī)組的名字為 sunx325b_groupHostName:sunx325b # 這個(gè)主機(jī)名為 sunx325bPort0:210000e08b0e934d # 第一個(gè) HBA 卡的 wwpn 值Port1:210000e08b0e6e50 # 第二個(gè) HBA 卡的 wwpn 值HostType:8 # 主機(jī)類型
復(fù)制 ds4kscript.sh 到和 config 相同的目錄下,執(zhí)行:chmod +x ds4kscript.sh (使用戶對(duì) ds4kscript.sh 具有執(zhí)行權(quán)限)./ds4kscript.sh ( 執(zhí)行 ds4kscript.sh)
在 ds4kscript.sh 運(yùn)行的目錄下,一系列文件將會(huì)被創(chuàng)建出來(lái):crtlun.cmd, crthost.cmd, maplun.cmd, delmap.cmd, delhost.cmd, dellun.cmd, setup.cmd, destroy.cmd。下面逐一對(duì)這些文件的功能進(jìn)行描述:
創(chuàng)建 Lun、host group、host、host port,映射 Lun。它包括了 crtlun.cmd, crthost.cmd, maplun.cmd 的所有功能,算是一個(gè)功能集合的腳本。
創(chuàng)建 Luns;
創(chuàng)建 host group、host、host port;
映射端口到 host 上;
刪除 Lun、host group、host、host port,映射 Lun。它包括了 delmap.cmd, delhost.cmd, dellun.cmd 的所有功能,算是一個(gè)功能集合的腳本;
刪除 Lun 映射
刪除 host group、host、host port
刪除 Lun
復(fù)制 setup.cmd 的內(nèi)容到 IBM Storage Manager 腳本編輯器中,然后運(yùn)行它。或者用戶也可以單獨(dú)的復(fù)制 crtlun.cmd, crthost.cmd, maplun.cmd 中的內(nèi)容,來(lái)實(shí)現(xiàn)單獨(dú)的一些功能。這時(shí) Lun 已經(jīng)在 DS4000 上建立好了,同時(shí)也映射到了主機(jī)上。
當(dāng)然,同時(shí)可以執(zhí)行 destroy.cmd 內(nèi)的內(nèi)容來(lái)進(jìn)行刪除操作,或者單獨(dú)地執(zhí)行 delmap.cmd, delhost.cmd, dellun.cmd 內(nèi)的內(nèi)容來(lái)清除剛才執(zhí)行的創(chuàng)建操作。
下面是 ds4kscript.sh 的詳細(xì)內(nèi)容,請(qǐng)注意其中的注解內(nèi)容,會(huì)幫助您的理解:下面是 ds4kscript.sh 的詳細(xì)內(nèi)容,請(qǐng)注意其中的注解內(nèi)容,會(huì)幫助您的理解:#ConfigFile=./configProgramName=./ds4kscript.shif [ -f $ConfigFile ]thenecho "OK" >> /dev/nullelseecho "$ConfigFile not exist!"exit -1fi# 從配置文件中依次獲取參數(shù)值sed -n '/LunNumber:/'p $ConfigFile >tmplunNumber=`sed 's/LunNumber://' tmp`echo lunNumber=$lunNumbersed -n '/ArrayNumber:/'p $ConfigFile >tmparrayNumber=`sed 's/ArrayNumber://' tmp`echo arrayNumber=$arrayNumbersed -n '/LunName:/'p $ConfigFile >tmplunName=`sed 's/LunName://' tmp`echo lunName=$lunNamesed -n '/Capacity:/'p $ConfigFile >tmpcapacity=`sed 's/Capacity://' tmp`echo capacity=$capacitysed -n '/HostGroupName:/'p $ConfigFile >tmphostGroupName=`sed 's/HostGroupName://' tmp`echo hostGroupName=$hostGroupNamesed -n '/HostName:/'p $ConfigFile >tmphostName=`sed 's/HostName://' tmp`echo hostName=$hostNamesed -n '/Port0:/'p $ConfigFile >tmpport0=`sed 's/Port0://' tmp`echo port0=$port0sed -n '/Port1:/'p $ConfigFile >tmpport1=`sed 's/Port1://' tmp`echo port1=$port1sed -n '/HostType:/'p $ConfigFile >tmphostType=`sed 's/HostType://' tmp`echo hostType=$hostType# 創(chuàng)建 IBM storage manager 使用的腳本中創(chuàng)建 Lun 的部分,并保存為 crtlun.cmd。if [ -f crtlun.cmd ]thenrm crtlun.cmdelseecho "OK" >> /dev/nullfix=0while [ $x -lt $lunNumber ]doy=`expr $x % 2`if [ $y -eq 0 ]thenecho "create logicalDrive array=$arrayNumber userLabel="${lunName}_${x}"capacity=$capacity owner=a;" >> crtlun.cmdelseecho "create logicalDrive array=$arrayNumber userLabel="${lunName}_${x}"capacity=$capacity owner=b;" >> crtlun.cmdfix=`expr $x + 1`done# 創(chuàng)建 IBM storage manager 使用的腳本中創(chuàng)建 host group,host 和 host port 的部分,并保存為 crthost.cmd。if [ -f crthost.cmd ]thenrm crthost.cmdelseecho "OK" >> /dev/nullfiecho "create hostGroup userLabel="$hostGroupName";" >>crthost.cmdecho "create host userLabel = "$hostName" hostGroup = "$hostGroupName";" >>crthost.cmdecho "create hostPort identifIEr = "$port0" userLabel = "${hostName}_hba0"host = "$hostName" hostType = $hostType;" >>crthost.cmdecho "create hostPort identifier = "$port1" userLabel = "${hostName}_hba1"host = "$hostName" hostType = $hostType;" >>crthost.cmd# 創(chuàng)建 IBM storage manager 使用的腳本中映射 Lun 的部分,并保存為 maplun.cmd。if [ -f maplun.cmd ]thenrm maplun.cmdelseecho "OK" >> /dev/nullfix=0while [ $x -lt $lunNumber ]doecho "set logicalDrive ["${lunName}_${x}"] logicalUnitNumber=$xhostGroup="$hostGroupName";" >>maplun.cmdx=`expr $x + 1`done# 創(chuàng)建 IBM storage manager 使用的腳本中刪除 Lun 映射的部分,并保存為 delmap.cmd。if [ -f delmap.cmd ]thenrm delmap.cmdelseecho "OK" >> /dev/nullfix=0while [ $x -lt $lunNumber ]doecho "remove logicalDrive ["${lunName}_${x}"] lunMappinghostGroup="$hostGroupName";" >>delmap.cmdx=`expr $x + 1`done# 創(chuàng)建 IBM storage manager 使用的腳本中刪除 Lun 的部分,并保存為 dellun.cmd。if [ -f dellun.cmd ]thenrm dellun.cmdelseecho "OK" >> /dev/nullfix=0while [ $x -lt $lunNumber ]doecho "delete logicalDrive ["${lunName}_${x}"];" >>dellun.cmdx=`expr $x + 1`done# 創(chuàng)建 IBM storage manager 使用的腳本中刪除 host port 的部分,并保存為 delhost.cmd。if [ -f delhost.cmd ]thenrm delhost.cmdelseecho "OK" >> /dev/nullfiecho "delete hostPort ["$port0"];" >>delhost.cmdecho "delete hostPort ["$port1"];" >>delhost.cmdecho "delete host ["$hostName"];" >>delhost.cmdecho "delete hostGroup ["$hostGroupName"];" >>delhost.cmd# 創(chuàng)建 IBM storage manager 使用的 2 個(gè)功能集合腳本,并分別保存為 setup.cmd 和 destroy.cmd。if [ -f setup.cmd ]thenrm setup.cmdelseecho "OK" >> /dev/nullficat crtlun.cmd >>setup.cmdcat crthost.cmd >>setup.cmdcat maplun.cmd >>setup.cmdif [ -f destroy.cmd ]thenrm destroy.cmdelseecho "OK" >> /dev/nullficat delmap.cmd >>destroy.cmdcat delhost.cmd >>destroy.cmdcat dellun.cmd >>destroy.cmd
總結(jié)
從上面可以看出,整個(gè)腳本使用的技術(shù)不是很復(fù)雜,主要是利用 SED 編輯器通過(guò)模式匹配從配置文件中提取出所需要的部分,然后從新組織起來(lái),形成一定的符合 IBM storage manager 使用的格式。其中還利用了一些簡(jiǎn)單的正則表達(dá)式,這在很多系統(tǒng)管理的腳本中很常見(jiàn),可見(jiàn)功能的實(shí)效性。當(dāng)然,作為 SED 這個(gè)強(qiáng)大的編輯器,功能遠(yuǎn)遠(yuǎn)不止這些,這里也是希望能通過(guò)我的一些實(shí)踐和大家分享一些使用腳本的心得。最終的目的還是提高工作的效率,哪一個(gè)管理員或是相關(guān)的工程師也不希望總是做一些沒(méi)有技術(shù)含量而且重復(fù)性很大的工作,所以腳本以及 SED 編輯器,Awk 等工具都是各位很好的幫手。下面看一下所生成的兩個(gè)功能集合腳本的內(nèi)容,體驗(yàn)一下成果的滋味。
setup.cmd
create logicalDrive array=1 userLabel="sunx325b_0" capacity=0.5GB owner=a;create logicalDrive array=1 userLabel="sunx325b_1" capacity=0.5GB owner=b;create logicalDrive array=1 userLabel="sunx325b_2" capacity=0.5GB owner=a;create logicalDrive array=1 userLabel="sunx325b_3" capacity=0.5GB owner=b;create logicalDrive array=1 userLabel="sunx325b_4" capacity=0.5GB owner=a;....create logicalDrive array=1 userLabel="sunx325b_26" capacity=0.5GB owner=a;create logicalDrive array=1 userLabel="sunx325b_27" capacity=0.5GB owner=b;create logicalDrive array=1 userLabel="sunx325b_28" capacity=0.5GB owner=a;create logicalDrive array=1 userLabel="sunx325b_29" capacity=0.5GB owner=b;create hostGroup userLabel="sunx325b_group";create host userLabel = "sunx325b" hostGroup = "sunx325b_group";create hostPort identifIEr = "210000e08b0e934d" userLabel = "sunx325b_hba0"host = "sunx325b" hostType = 8;create hostPort identifier = "210000e08b0e6e50" userLabel = "sunx325b_hba1"host = "sunx325b" hostType = 8;set logicalDrive ["sunx325b_0"] logicalUnitNumber=0 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_1"] logicalUnitNumber=1 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_2"] logicalUnitNumber=2 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_3"] logicalUnitNumber=3 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_4"] logicalUnitNumber=4 hostGroup="sunx325b_group";....set logicalDrive ["sunx325b_25"] logicalUnitNumber=25 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_26"] logicalUnitNumber=26 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_27"] logicalUnitNumber=27 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_28"] logicalUnitNumber=28 hostGroup="sunx325b_group";set logicalDrive ["sunx325b_29"] logicalUnitNumber=29 hostGroup="sunx325b_group";
destroy.cmd
remove logicalDrive ["sunx325b_0"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_1"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_2"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_3"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_4"] lunMapping hostGroup="sunx325b_group";....remove logicalDrive ["sunx325b_25"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_26"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_27"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_28"] lunMapping hostGroup="sunx325b_group";remove logicalDrive ["sunx325b_29"] lunMapping hostGroup="sunx325b_group";delete hostPort ["210000e08b0e934d"];delete hostPort ["210000e08b0e6e50"];delete host ["sunx325b"];delete hostGroup ["sunx325b_group"];delete logicalDrive ["sunx325b_0"];delete logicalDrive ["sunx325b_1"];delete logicalDrive ["sunx325b_2"];delete logicalDrive ["sunx325b_3"];delete logicalDrive ["sunx325b_4"];delete logicalDrive ["sunx325b_5"];....delete logicalDrive ["sunx325b_25"];delete logicalDrive ["sunx325b_26"];delete logicalDrive ["sunx325b_27"];delete logicalDrive ["sunx325b_28"];delete logicalDrive ["sunx325b_29"];
