ESX 4.1 में "sbin / powerOffVms"

कार्यालय में प्रबंधन, जहां मैं काम करता हूं, बैटरी ऑपरेशन के लिए निर्बाध स्विच करने पर सर्वर के स्वत: बंद करने के लिए कार्य सेट करता है। कुछ सर्वर विंडोज़ पर चलते हैं (मैंने उनके बारे में कभी सोचा भी नहीं था) और कुछ esx / esxi पर थे, जो मुझे सबसे ज्यादा परेशान करते थे, क्योंकि मेरे पास निक्स के साथ काम करने का बहुत कम अनुभव है, खासकर सभी तरह की स्क्रिप्ट लिखना। लेकिन कार्य निर्धारित है और इसे हल करना आवश्यक है।
मैंने धीरे-धीरे इस मुद्दे का अध्ययन करना शुरू कर दिया, और जब मैं esxi 5.x powerOffVms में बाइनरी के लिए गया था, तो मुझे वास्तव में खुशी हुई, जो संबंधित विकल्प चालू होने पर अतिथि सिस्टम को बंद कर देता है। लेकिन उत्साह तब कम हो गया जब इस तरह की चीज को एसएक्स संस्करण में नहीं मिला। सामान्य तौर पर, इस सुविधा को esx में बैश पर लागू करने का निर्णय लिया गया (बस यह समझने के लिए कि वह किसलिए और क्यों सांस ले रहा है)।

नीचे जाने वाली सभी चीजों को विभिन्न तरीकों से लागू किया जा सकता है, जो अधिक सही हो सकती है, लेकिन मैं योजना को फेंकना नहीं चाहता था।

पहली चीज़ जो मैंने की थी वह एक विशिष्ट वर्चुअल मशीन को बंद कर दिया था। ऐसा करने के लिए, इसकी स्थिति का पता लगाना आवश्यक था, और एसएक्स कमांड यह क्या करते हैं। नियमावली पर लौटते हुए हमें अधिकार है ...

vim-cmd vmsvc / power.getstate मशीन स्थिति
vim-cmd vmsvc / power.shutdown शटडाउन अतिथि OS
vim-cmd vmsvc / power.off power off अतिथि ओएस

भविष्य में मैं स्पष्टता चाहता था, और अधिक सटीक होने के लिए, स्क्रिप्ट के निष्पादन के दौरान, मशीन के नाम का आउटपुट जिसे फटा जा सकता था

vim-cmd vmsvc / get.summary

वर्चुअल मशीन की आईडी को जानने के बाद, हम इसका नाम स्पष्टता के लिए लेते हैं और अतिथि OS को बंद करने का प्रयास करते हैं। लेकिन ओएस को सही ढंग से बंद करने के लिए, स्थापित vmware टूल और "अतिथि शटडाउन" पुश आवश्यक हैं। और यह सब व्यवसाय यह जांचने के लिए है कि मशीन बंद हो गई या लटका दी गई और पूरा होने की प्रक्रिया की जांच करने के लिए कितना समय है। एक बार फिर, हम मैनुअल धूम्रपान करते हैं और स्टॉपडेल के रूप में ऐसी चीज ढूंढते हैं, जिसे vsphere क्लाइंट के माध्यम से सेट किया जा सकता है, और डिफ़ॉल्ट रूप से यह 120 सेकंड है। इसे यहाँ से फाड़ा जा सकता है:

vim-cmd होस्ट्समेक / 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 ) } 


वर्चुअल मशीन बंद कर रहा है। शटडाउन प्रक्रिया को निलंबित कर दिया जाता है, तो कितनी देर तक बिजली बंद हो जाएगी, इसके बाद फ़ंक्शन को मशीन आईडी और विलंब मूल्य प्राप्त होता है।

 # 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!!!" } 


मैं यहां क्या कर रहा हूं, मुझे GetBootOrder फ़ंक्शन में वर्चुअल मशीनों को शामिल करने का आदेश मिला है, जो उन मूल्यों की एक सरणी देता है जिनके सूचकांक 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" के साथ। लेकिन क्या हो अगर किसी एक मशीन का शटडाउन लटका रहे। हमें काम के परिणाम की जांच करने की आवश्यकता है ... यहां एक और ControlVerboseShutDown फ़ंक्शन लागू किया गया है, जो समय की एक निर्दिष्ट अवधि के बाद मशीनों की स्थिति की दोहरी जांच करेगा, अर्थात। इसके स्टॉपडेल के अनुसार प्रत्येक वर्चुअल मशीन के लिए। कुछ भी आविष्कार करने की आवश्यकता नहीं है, सब कुछ लिखा है - सब कुछ अध्ययन किया गया है।

 # 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 


इसलिए हमें पावरऑफवे एससीआई 5.1 का लगभग पूरा एनालॉग मिला। लिखने की प्रक्रिया में, हमने बोलने की मूल बातें, grep और sed उपयोगिताओं और थोड़े से नियमित भावों को सीखा, इसलिए बोलना सीख लिया।
यह समस्या, निश्चित रूप से, अन्य तरीकों से हल की जा सकती है:

PowerCLI के लिए PowerShell स्क्रिप्ट
vash बैश स्क्रिप्टिंग के साथ
pyshpere api
VIX एपीआई

लेकिन मैं वहाँ नहीं रुका और पूरी चीज को esxi 5.1 पर लॉन्च किया, और वहां कोई बैश नहीं है (मुझे इसे जोड़ना पड़ा)। यह सब अगले लेख में वर्णित किया जा सकता है, यदि आप निश्चित रूप से रुचि रखते हैं।

Source: https://habr.com/ru/post/In188726/


All Articles