ESX 4.1の「/ sbin / powerOffVms」

私が勤務しているオフィスの管理者は、バッテリー操作への無停電の切り替え時に、サーバーの自動シャットダウンを実行するタスクを設定しました。 一部のサーバーはWindows上で実行され(私も考えていませんでした)、esx / esxiで実行されました。これは、特にあらゆる種類のスクリプトを作成するnixの操作経験がほとんどないため、最も悩みました。 しかし、タスクは設定されており、それを解決する必要があります。

私はこの問題をゆっくりと研究し始めました。esxi5.x powerOffVmsのバイナリに移動すると、対応するオプションがオンになったときにゲストシステムをシャットダウンしました。 しかし、esxバージョンでそのようなことが見つからなかった場合、熱意は低下しました。 一般に、esxのbashにこの機能を実装することが決定されました(彼が何を求めているのか、そしてその理由を理解するためだけです)。



以下のすべてはさまざまな方法で実装できますが、より正確かもしれませんが、私は計画を投げたくありませんでした。



最初にしたことは、特定の仮想マシンをシャットダウンすることでした。 これを行うには、そのステータスと、これを行うesxコマンドを調べる必要がありました。 マニュアルに戻ると、我々には権利があります...



vim-cmd vmsvc / power.getstateマシン状態

vim-cmd vmsvc / power.shutdownシャットダウンゲストOS

vim-cmd vmsvc / power.off電源オフゲストOS



将来的には、スクリプトの実行中に、引き裂く可能性のあるマシンの名前の出力を明確にし、より正確にしたかった



vim-cmd vmsvc / get.summary



仮想マシンのIDを知っているため、わかりやすいようにその名前を取得して、ゲストOSをシャットダウンしようとします。 ただし、OSを正しくシャットダウンするには、インストールされたvmwareツールと「ゲストシャットダウン」プッシュが必要です。 そして、このすべてのビジネスは、マシンがオフになったかハングしたか、完了プロセスをチェックする時間をチェックすることです。 もう一度、マニュアルを吸って、vSphereクライアントを介して設定できるstopDelayなどを見つけます。デフォルトでは120秒です。 ここから破れます:



vim-cmd hostsvc / hostconfig



しかし、ここでも微妙な違いがありました。起動順序が設定されていないと、この遅延の値はそこにありません。

だから私たちは何を持っています...



車の名前を取得する



# get vm name via VMID # $1 - VMID function GetVMName () { vmName=$(vim-cmd vmsvc/get.summary $1 | grep "name" | sed 's/.*"\(.*\)"[^"]*$/\1/') }
      
      







シャットダウン遅延値の配列を取得します。 包含順序が設定されていない場合、配列が完全ではない可能性があることを再度注意します。 次は、この問題を解決する方法に関する「松葉杖」です。



 # get stop delay options of vms function GetStopDelay () { OUT=$(vim-cmd hostsvc/hostconfig | grep "stopDelay" | sed 's/[^-0-9]//g') stopDelay=( $OUT ) }
      
      







仮想マシンをシャットダウンします。 この関数は、シャットダウンプロセスが中断された場合に電源がオフになった後のマシンIDと遅延値を受け取ります。



 # vm shutdown # passing parameters to the function # echo "VMShutDown $1 $2" # $1 - VMId, $2 - stopDelay function VMShutDown () { GetVMName $1 stopTime=0 STATE=$(vim-cmd vmsvc/power.getstate $1 | grep "Power") if [ "$STATE" = "Powered off" ] then echo "VM $1 ($vmName) is stopped. " return 1 fi echo "Call VM $1 ($vmName) shutdown..." vim-cmd vmsvc/power.shutdown $1 sleep 5 if [ "$stopTime" -eq 0] then echo "Waiting for VM $1 ($vmName) shutdown..." fi while [ "$STATE" != "Powered off" ] do if [ "$stopTime" -ge "$2" ] then echo "Shutdown of VM $1 ($vmName) causes to fail. Call power off!" vim-cmd vmsvc/power.off $1 return 2 fi STATE=$(vim-cmd vmsvc/power.getstate $1 | grep "Power") stopTime=$(($stopTime+5)) sleep 5 done echo "VM $VM ($vmName) shutdown is successfully" return 3 }
      
      







計画には少なくともいくつかがありましたが、スクリプトの汎用性があるため、特定のマシンの電源を切ることはこの機能で形になりました...



 # specific VM Shutdown # $1 - VMId function SpecificVMShutDown () { GetVMName $1 GetBootOrder element=1 for VM in ${bootOrder[@]} do if [ "$VM" -eq "$1" ] then GetVmStopDelay "${stopDelay[0]}" "${stopDelay["$element"]}" VMShutDown $VM $currentDelay return 1 fi element=$(($element+1)) done echo "VMId $1 is not found!!!" }
      
      







ここで何をしているのか、GetStopOrder関数に仮想マシンを含める順序を取得します。この関数は、GetStopDelayの配列のインデックスに完全に対応するインデックスを持つ値の配列を返します。 そして、両方とも完全ではないかもしれません(私が上で示した理由)。 それからちょっとしたトリック、つまり松葉杖に行きます。 配列にないマシンの配列にデフォルトデータを追加します。 どのような種類のマシンがまったく設定されていないかを理解するには、最初に次のようにしてリスト全体を取得する必要がありました。



vim-cmd vmsvc / getallvms



 # Get full list of VMs ID function GetAllVMs () { OUT=$(vim-cmd vmsvc/getallvms |grep -o '^[0-9]*') allVMs=( $OUT ) }
      
      







そして、もしあれば、配列に欠損値を追加します...



 # Find missed VMs in boot order # Add missed VM to boot order array function FindMissedVMs () { GetAllVMs for aVM in ${allVMs[@]} do exists=0 for oVM in ${bootOrder[@]} do if [ "$aVM" -eq "$oVM" ] then exists=1 break fi done if [ "$exists" -eq 0 ] then bootOrder=( "${bootOrder[@]}" "$aVM" ) stopDelay=( "${stopDelay[@]}" "-1" ) fi done }
      
      







さて、仮想マシンの起動順序を取得するまさに機能...



 # get boot order of vms function GetBootOrder () { OUT=$(vim-cmd hostsvc/hostconfig | grep "key = 'vim.VirtualMachine:" | sed 's/[^-0-9]//g') bootOrder=( $OUT ) GetStopDelay FindMissedVMs }
      
      







仮想マシンをオフにするか、GetVmStopDelay関数に戻りましょう。これは、使用する遅延の種類を決定します。 ここではすべてが簡単です。



 # use default or optional delay # $1 - default delay, $2 optional delay function GetVmStopDelay () { currentDelay="$1" if [ "$2" -gt 0 ] then currentDelay="$2" fi }
      
      







出力では、特定の仮想マシンをオフにし、この全体をチェックします。フリーズが発生した場合、電源がオフになります(実際には、これはまだ行われていません)。



次に、ブート順序に従ってマシンをオフにするタスクを自分で設定しました。 もう考える必要はありませんでした。 キューの値を含む配列を取得し、それぞれを調べて、指定された方法でマシンの電源を切ります。



 # order shutdown all VMS function OrderShutDown () { echo "Call order shutdown all VMs" GetBootOrder element=1 for VM in ${bootOrder[@]} do #echo "${stopDelay["$element"]}" GetVMName $VM echo "Beginning shutdown process: $vmName (VMID: $VM)..." GetVmStopDelay "${stopDelay[0]}" "${stopDelay["$element"]}" VMShutDown $VM $currentDelay element=$(($element+1)) done echo "Order shutdown has been executed" }
      
      







ここでは、車がたくさんある場合に注意を払う必要があります。シャットダウンプロセスには時間がかかる場合があります。 そして、バッテリーに切り替えるときが私たちのすべてです。 そのため、順序が重要でない場合にすべてのマシンをオフにする機能を作成することにしました。



 # verbose shutdown all VMS function VerboseShutDown () { echo "Call verbose shutdown all VMs" GetBootOrder for VM in ${bootOrder[@]} do STATE=$(vim-cmd vmsvc/power.getstate $VM | grep "Power") if [ "$STATE" != "Powered off" ] then GetVMName $VM echo "Call VM $VM ($vmName) shutdown" vim-cmd vmsvc/power.shutdown $VM fi done ControlVerboseShutDown }
      
      







前の機能とは対照的に、直接コマンド「vim-cmd vmsvc / power.shutdown」を使用して、マシンはチェックなしでオフになります。 しかし、マシンの1つのシャットダウンがハングした場合はどうでしょう。 作業の結果を確認する必要があります...ここで、別のControlVerboseShutDown関数が実装されます。これは、指定された期間の後、つまりマシンの状態を再確認します。 stopDelayに従って各仮想マシンに対して。 何も発明する必要はありません、すべてが書かれています-すべてが研究されています。



 # control process off verbose shutdown function ControlVerboseShutDown () { echo "Checking verbose shutdown all VMs" executed=0 stopTime=0 while [ "$executed" -eq 0 ] do errorCount=0 element=1 for VM in ${bootOrder[@]} do GetVMName $VM STATE=$(vim-cmd vmsvc/power.getstate $VM | grep "Power") if [ "$STATE" = "Powered off" ] then #echo "VM $VM ($vmName) is powered off. Checking next" element=$(($element+1)) continue fi if [ "$stopTime" -eq 0] then echo "Waiting for VM $1 ($vmName) shutdown..." fi GetVmStopDelay "${stopDelay[0]}" "${stopDelay["$element"]}" if [ "$stopTime" -ge "$currentDelay" ] then echo "Shutdown of VM $VM ($vmName) causes to fail. Call power Off!" vim-cmd vmsvc/power.off $VM fi errorCount=$(($errorCount+1)) element=$(($element+1)) done if [ "$errorCount" -eq 0 ] then echo "Verbose shutdown has been executed" executed=1 return 1 fi stopTime=$(($stopTime+10)) sleep 10 echo "Remaining time: $stopTime" done }
      
      







さて、パラメータを使用してスクリプト自体を呼び出す少し汎用性...



 while getopts ":os:v" optname do case "$optname" in "o") OrderShutDown exit 1 ;; "s") VMID=$OPTARG SpecificVMShutDown "$VMID" exit 2 ;; "v") VerboseShutDown exit 3 ;; esac done
      
      







したがって、powerOffVms esxi 5.1のほぼ完全な類似物が得られました。 執筆の過程で、bashの基本、grepおよびsedユーティリティ、およびいわば正規表現を少し学びました。

もちろん、この問題は他の方法でも解決できます。



PowerCLIのPowerShellスクリプト

bashスクリプトを使用したvMA

pyshpere api

VIX API



しかし、私はそこで停止せずにesxi 5.1ですべてを起動しましたが、bashはありません(追加する必要がありました)。 あなたがもちろん興味があるなら、これはすべて次の記事で説明することができます。



All Articles