はじめに #
第2回では、pyvmomiでvCenterにアクセスしESXiのオブジェクトを取得する方法を解説しました。
今回は取得したオブジェクトに簡単な命令を実行してみます。
1. ESXiを取得する #
詳しくは第2回の「6. ESXiを取得してみる」を参考に作業対象のESXiを取得ください。
実際に取得してesxi
という変数に格納しておきましょう。
from pyVim import connect
# service_instanceはsiとよく略される
si = connect.SmartConnect(
host=vc_ip,
user=vc_usr,
pwd=vc_pwd,
disableSslCertValidation=True
)
esxi = si.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0]
print(esxi.name)
>>>v10-nesxi-01.lab.local
2. ESXiのリソース情報の取得 #
esxi.summary.quickStats
やesxi.summary.hardware
のように膨大で複雑なMOBの中で、自分が欲しい情報がどこにあるか探す方法は第6回で紹介します。
まずは以下の画像のようなESXiのリソース情報を取得してみます。
- 性能がCPU:6.4GHz(2コア)、MEM:8GB
- 使用率がCPU:115MHz、MEM:1.93GB
現在のリソース使用量 #
esxiの現在のリソース使用量は<esxiのobject>.summary.quickStats
で取得することができます。公式のdocs
print(esxi.summary.quickStats)
>>>(vim.host.Summary.QuickStats) {
dynamicType = <unset>,
dynamicProperty = (vmodl.DynamicProperty) [],
overallCpuUsage = 114,
overallMemoryUsage = 1982,
distributedCpuFairness = 10000,
distributedMemoryFairness = 10000,
availablePMemCapacity = 0,
uptime = 57515
}
overallCpuUsage = 114
のように単位がMOBにもpyvmomiにも出力されていないため不明になることがあります。今回のようにGUIと比較することで推定もできますが、明確に知りたい場合は変数名「overallCpuUsage vsphere」や、データの型名「vim.host.Summary.QuickStats」で検索してみてください。すると公式のdocsがhitして説明を見ることができます。
スペック情報 #
esxiのスペック情報は<esxiのobject>.summary.hardware
で取得することができます。
memorySize = 8588832768
が公式のdocsを見るとbytesとなっており、分かりづらいですがvCenterと同じ値が取得できています。
The physical memory size in bytes.
print(esxi.summary.hardware)
>>>(vim.host.Summary.HardwareSummary) {
dynamicType = <unset>,
dynamicProperty = (vmodl.DynamicProperty) [],
vendor = 'VMware, Inc.',
model = 'VMware7,1',
uuid = 'a56c1542-2895-909e-c819-0f0926f54e87',
...
memorySize = 8588832768,
cpuModel = 'AMD Ryzen 7 5800H with Radeon Graphics ',
cpuMhz = 3194,
numCpuPkgs = 2,
numCpuCores = 2,
numCpuThreads = 2,
numNics = 2,
numHBAs = 3
}
これがMOBのProperties情報を取得する例になります。基本的にMOBと同じ階層をpyvmomiでも指定するだけなので簡単ですね。
3. ESXiをメンテモード化 #
今度はMOBのMethodsを実行する例として、ESXiのメンテナンスモード化を実施します。
メンテモード化用のMethodsは、<esxiのobject>.EnterMaintenanceMode_Task()
になります。MethodsはPropertiesと違い関数なので引数が必要になる場合が多いです。
この引数はMOBでMethodをclickするとある程度確認できる + Method名で検索して公式のdocsを探すのが良いです。
この情報を元にpythonで書くと以下のようになります。これだけでもesxiをメンテモードにできますがvim.Task:task-236
というオブジェクトが返却されているのが分かります。
このtaskを用いることでMethodsがsuccess or running or errorかを判別することができるようになります。
esxi = si.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0]
print(esxi.name)
>>>v10-nesxi-01.lab.local
task = esxi.EnterMaintenanceMode_Task(timeout=10) # timeoutを10sに設定
print(task)
>>> 'vim.Task:task-236'
4. taskを使ってMethodsの結果を制御 #
先ほどのtaskですが、task番号はvim.Task:task-236
は表示されないものの、それ以外はvCenterで表示されるtaskと同じになります。これからの作業はこのtaskを確認する処理と思ってもらうと分かりやすいと思います。
実際にtaskのオブジェクトを確認すると状況に応じて、success or running or errorか判別することができるようになります。これを使うことでMethodsをより便利にハンドリングできます。
# Methodsの結果をtaskに格納する。
task = esxi.EnterMaintenanceMode_Task(timeout=10) # timeoutを10sに設定
print(task)
>>> 'vim.Task:task-236'
# task.infoで状態を確認する。
print(task.info) ## 結果の確認(実行中の場合)
>>> (vim.TaskInfo) {
description = (vmodl.LocalizableMessage) {
key = 'com.vmware.vim.vpxd.enterUnavailableMode.waitVmPowerOffOrMigration',
message = 'Waiting for all VMs to be powered off or suspended or migrated. In a DRS cluster check the Faults page on the DRS tab for troubleshooting.'
},
state = 'running',
print(task.info) ## 結果の確認(成功の場合)
>>> (vim.TaskInfo) {
description = <unset>,
state = 'success',
...
print(task.info) ## 結果の確認(失敗の場合)
>>> (vim.TaskInfo) {
description = (vmodl.LocalizableMessage) {
key = 'com.vmware.vim.vpxd.enterUnavailableMode.hostEMMTimedout',
message = 'Entering maintenance mode task has been timed out'
},
state = 'error',
これらを踏まえてより実用的には、以下のようにtaskを定期的にcheckしてあげる必要があります。
from pyVim import connect
import time
si = connect.SmartConnect(
host=vc_ip,
user=vc_usr,
pwd=vc_pwd,
disableSslCertValidation=True
)
esxi = si.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0]
# 現在メンテナンスモードではない & hostに存在するVM数が0の場合にのみ、メンテナンスモード化を実行する。
if (host.runtime.inMaintenanceMode is False) and (len(host.vm) == 0):
task = host.EnterMaintenanceMode_Task(timeout=100)
# taskがrunning中なら待つ
while task.info.state == "running":
print("task実行中...")
time.sleep(10)
# 成功じゃないならerror
if task.info.state != "success":
print(task.info.description.message)
raise ValueError("taskが失敗しました")
5. pyvmomiに搭載されているtask制御 #
ここまで解説のためにtaskのcheckを自作しましたが、実際にはpyvmomiに付属しているpyVim.task.WaitForTask()
を使うのが簡単なのでおすすめです。
from pyVim import task
# 成功のとき
print(task.WaitForTask(esxi.EnterMaintenanceMode_Task(timeout=10)))
>>> success
# 失敗の時には自動でerrorにしてくれる(既にメンテモードなのに、もう一度メンテモード化を実行した場合)
task.WaitForTask(esxi.EnterMaintenanceMode_Task(timeout=10))
>>>vim.fault.InvalidState: (vim.fault.InvalidState) {
dynamicType = <unset>,
dynamicProperty = (vmodl.DynamicProperty) [],
msg = 'The operation is not allowed in the current state.',
faultCause = <unset>,
faultMessage = (vmodl.LocalizableMessage) [
(vmodl.LocalizableMessage) {
dynamicType = <unset>,
dynamicProperty = (vmodl.DynamicProperty) [],
key = 'com.vmware.cdrs.maintenancemode.latch',
arg = (vmodl.KeyAnyValue) [
(vmodl.KeyAnyValue) {
...
],
message = 'Host v10-nesxi-01.lab.local cannot enter maintenance mode due to host latch failure.'
}
]
}
pyvmomi-community-sampleというpyvmomiのsampleを集めたページがありますが、そこではwait_for_tasks()
という別のtaskのcheck関数が使われています。これはcommunity-sample内で独自実装されたもので、pyVim.task.WaitForTask()
と違うので注意しましょう。
使うにはpyVimのimportではなく、pyvmomi-community-sampleのcodeをコピーする必要があります。
from tools.tasks import wait_for_tasks # importが違う!!
# Find the vm and power it on
tasks = [vm.PowerOn() for vm in vm_list if vm.name in vmnames]
# Wait for power on to complete
wait_for_tasks(si, tasks)
おわりに #
今回はESXiのオブジェクトに対して「情報取得(MOBのProperties)」「命令実行(MOBのMethods)」を実行してみました。 第4回はVMのオブジェクトに対して同じようなことを実施して、基本のオブジェクトの扱い方をマスターできればと思います。