メインコンテンツへスキップ
  1. Blogs/

pyvmomiで自動化3 -ESXiに命令実行-

·2981 文字·
Blog VMware VSphere Pyvmomi Python
hiroki
著者
hiroki
クラウドを作るお仕事をしてます。
目次
pyvmomi - 関連記事
3: << この記事 >>

はじめに
#

第2回では、pyvmomiでvCenterにアクセスしESXiのオブジェクトを取得する方法を解説しました。

今回は取得したオブジェクトに簡単な命令を実行してみます。

1. ESXiを取得する
#

詳しくは第2回の「6. ESXiを取得してみる」を参考に作業対象のESXiを取得ください。

pyvmomiで自動化2 -vCenterにアクセス-
·3692 文字
Blog VMware VSphere Pyvmomi Python

実際に取得して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.quickStatsesxi.summary.hardwareのように膨大で複雑なMOBの中で、自分が欲しい情報がどこにあるか探す方法は第6回で紹介します。

まずは以下の画像のようなESXiのリソース情報を取得してみます。

  • 性能がCPU:6.4GHz(2コア)、MEM:8GB
  • 使用率がCPU:115MHz、MEM:1.93GB

img001

現在のリソース使用量
#

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
    }

img002

overallCpuUsage = 114のように単位がMOBにもpyvmomiにも出力されていないため不明になることがあります。今回のようにGUIと比較することで推定もできますが、明確に知りたい場合は変数名「overallCpuUsage vsphere」や、データの型名「vim.host.Summary.QuickStats」で検索してみてください。すると公式のdocsがhitして説明を見ることができます。
img003

スペック情報
#

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
    }

img004

これがMOBのProperties情報を取得する例になります。基本的にMOBと同じ階層をpyvmomiでも指定するだけなので簡単ですね。

3. ESXiをメンテモード化
#

今度はMOBのMethodsを実行する例として、ESXiのメンテナンスモード化を実施します。

メンテモード化用のMethodsは、<esxiのobject>.EnterMaintenanceMode_Task()になります。MethodsはPropertiesと違い関数なので引数が必要になる場合が多いです。 この引数はMOBでMethodをclickするとある程度確認できる + Method名で検索して公式のdocsを探すのが良いです。

とはいえMethodsの引数紹介はMOBの画面やdocsだけでは値のsampleも無いので不十分であることが多いです。この解決策としてはMethod名で検索して実際に使っている例を見つける等がありますが、より具体的な引数確認方法は第5回で紹介します。

img005

この情報を元に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を確認する処理と思ってもらうと分かりやすいと思います。

img006

実際に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',
pyvmomiはtaskがerrorであっても、pythonのErrorを出力しcodeを停止してくれません。(権限不足でそもそもMethodsを実行できない場合等を除く) 従ってtaskの中身を見て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のオブジェクトに対して同じようなことを実施して、基本のオブジェクトの扱い方をマスターできればと思います。

pyvmomi - 関連記事
3: << この記事 >>

Related

pyvmomiで自動化1 -MOBを触ってみよう-
·2382 文字
Blog VMware VSphere Pyvmomi Python
pyvmomiで自動化2 -vCenterにアクセス-
·3692 文字
Blog VMware VSphere Pyvmomi Python
ansibleでvyosのclone
·1307 文字
Blog VMware VSphere Ansible Python