はじめに #
第1回では、pyvmomiを使う前準備としてManagement Object Browser(MOB)について解説しました。
今回は実際にpyvmomiを利用してvCenterにアクセス + 各オブジェクトを触ってみます。
1. pyvmomiとは? #
pyvmomiはvSphereを操作できるSDKで、pythonを使用してvSphereの自動化を実施するにはこちらを使うことになります。
pyvmomiのメリットしては、
- 利用ユーザーの多いpythonでvSphereの自動化を実施できる。
- Ansible等の操作内容が定まっている自動化ツールよりも、pythonで自由にコードを記載できるので柔軟な操作できる。
- 非常に広範囲のAPIをカバーしており、vSphereで実施するほぼ全ての作業がpyvmomiから実施できる。
があります。
特にpythonで自由にコードを記述できるのが便利で、膨大なVMのデータをpandas(pythonのデータ分析ライブラリ)で解析をよく実施しています。
VMware vSphere API Python Bindings
2. pyvmomiのinstall #
pipを使用してinstallだけでOKなので、非常に簡単です。
pip install pyvmomi
pyvmomi>=7.0
(vSphere7以上)を対象に解説します。
しかし後方互換性があるので最新のpyvmomi8.0を使用しても、vSphere6.5まではほとんどの機能が動きます。詳細はpyvmomiの公式HP を参照ください。
3. vCenterにアクセスする #
まずはpyvmomiでvCenterに接続して、MOBのtopであるServiceInstanceを取得します。
vCenter接続用の関数pyVim.connect.SmartConnect
を使います。問題なく接続できるとServiceInstanceのオブジェクト名vim.ServiceInstance:ServiceInstance
がprintされます。
# pyvmomiには2つのパッケージpyVimとpyVmomiが存在するが、今回はvCenterに接続するためのconnectパッケージが存在するpyVimをimport
from pyVim import connect
# ServiceInstanceはsiとよく略される
si = connect.SmartConnect(
host="***", # vCenter/ESXiのip, fqdn
user="***", # vCenterにloginするuser
pwd="***", # vCenterにloginするpassword
disableSslCertValidation=True # 証明書チェックをしない(vCenterが発行したオレオレ証明書なので)
)
print(si)
# >>> 'vim.ServiceInstance:ServiceInstance'
pyvmomiでは900s経過すると自動でsessionがcloseします。その場合は再度connect.SmartConnect
を使うか、connectionPoolTimeout=
で指定しましょう。
si = connect.SmartConnect(
host="***",
user="***",
pwd="***",
disableSslCertValidation=True
connectionPoolTimeout=1200 # 単位は秒
pyvmomi<=7.0.3
までは証明書確認skip専用のSmartConnectNoSSL
も存在しましたが、pyvmomi>=8.0.0
から削除されました。webで公開されているsampleにはこのSmartConnectNoSSLを使っている例も多いので注意してください。
もしvCenterにアクセスできないときは以下のエラーが出ますので、確認して対処をしましょう。
# login情報が間違っている
vim.fault.InvalidLogin: Traceback (most recent call last)
dynamicProperty = (vmodl.DynamicProperty) [],
msg = 'Cannot complete login due to an incorrect user name or password.',
faultCause = <unset>,
faultMessage = (vmodl.LocalizableMessage) []
# vCenterに疎通できない場合(ip間違えなど)
OSError: [Errno 113] No route to host
4. ServiceInstanceを細かくみる #
上記で取得したvim.ServiceInstance:ServiceInstance
ですが、このままではオブジェクト名しか表示されないので以下コマンドを実行します。
print(dir(si))
# >> ['Array',
# 'CurrentTime',
# 'QueryVMotionCompatibility',
# 'RetrieveContent',
# '__class__',
# '__delattr__',
# '__dict__',
# '__dir__',
# '__doc__',
# '__eq__',
# '__format__',
# '__ge__',
# '__getattribute__',
# ...
# '_version',
# '_wsdlName',
# 'capability',
# 'content',
# 'serverClock']
dir()
関数はpythonの標準ライブラリで、オブジェクトが持つ変数やメソッドをリストで出力してくれる。
これだと_
から始まるprivateな変数も出力され分かりにくいので、publicな変数だけにするとMOBのProperties, Methodsと一致することがわかります。
public_attributes = [
attr
for attr in dir(si)
if not attr.startswith('_')
]
print(public_attributes) # MOBのSerivceInstanceと一致する!!
# >>> ['Array',
# 'CurrentTime',
# 'QueryVMotionCompatibility',
# 'RetrieveContent',
# 'RetrieveProductComponents',
# 'RetrieveServiceContent',
# 'ValidateMigration',
# 'capability',
# 'content',
# 'serverClock']
このようにpyvmomiではMOBの情報を取得することができます。これが第1回でも紹介したMOBの重要性で「MOBで欲しい情報を見つける」→「pyvmomiで取得する」というのが基本のpyvmomiの扱い方になります。
5. 実際にデータを取得する #
pyvmomiとMOBの繋がりが分かったので実際にMOBのデータをpyvmomiで取得してみます。
si
#
# MOBのPropertiesは変数なので、`si.serverClock`のように指定するだけOK
print(si.serverClock)
# >>> 2024-05-02 13:09:22.257361+00:00
# MOBのMethodsは関数なので、`si.CurrentTime()`のように`()`や引数が必要です。
print(si.CurrentTime())
# >>> 2024-05-02 13:20:26.999703+00:00
si.content
#
ServiceInstance → content
に進むと画像のように多くのPropertiesが確認できます。ここがMOBの中でも最重要なデータ群になり、基本的にどんな作業をするにもまずはsi.content
にアクセスすることになります。いくつか抜粋した項目が以下表です。
name | pyvmomiのpath | 説明 |
---|---|---|
about | si.content.about | vCenterのverなど、vCenterに関するデータが記載 |
alarmManager | si.content.alarmManager | alarm定義や新規alarm作成など、alarmに関するデータ・関数が記載 |
rootFolder | si.content.rootFolder | 最重要 vCenterのインベントリーツリーのTOPに該当(ESXiやVMなどオブジェクトとTOPに該当) |
si
と同様にpyvmomiでも同じPropertiesが取得できることが分かります。
public_attributes = [
attr
for attr in dir(si.content)
if not attr.startswith('_')
]
print(public_attributes)
# >>>['Array',
# 'about',
# 'accountManager',
# 'alarmManager',
# 'authorizationManager',
# 'certificateManager',
si.content.about
#
ServiceInstance → content → about
と進むと先ほど解説したように、vCenterの情報が取得できるようになります。
print(si.content.about)
# >>>(vim.AboutInfo) {
# dynamicType = <unset>,
# dynamicProperty = (vmodl.DynamicProperty) [],
# name = 'VMware vCenter Server',
# fullName = 'VMware vCenter Server 7.0.3 build-20150588',
# ### 省略 ###
# }
si.content.about
ではprintすると中身が表示されように、pyvmomiでは「オブジェクトの名前だけ表示」、「オブジェクトの中身を表示」する2パターンが存在します。あまり法則性はなさそうなので、オブジェクトはこまめにprintして中身を確認すると良いでしょう。
si.content.rootFolder
#
ServiceInstance → content → rootFolder
と進むと、最重要オブジェクトであるrootFolderに辿り着くことができます。これはvCenterではインベントリツリーのTOPに該当し、VM,ESXi,Cluster,Datastore,Network等のオブジェクトにアクセスする際の入り口になります。
詳しくは第1回の「フォルダ階層を辿る」を参考ください。
6. ESXiを取得してみる #
ここまでpyvmomiの使い方が分かったと思うので、ちょっと難解なESXiのオブジェクトの取得を実施してみます。
まずはrootFolderを経由して、Datacenterの1階層下(cluster)まで取得します。
from pyVim import connect
si = connect.SmartConnect(
host=vc_ip,
user=vc_usr,
pwd=vc_pwd,
disableSslCertValidation=True
)
# まずはrootFolderにアクセス
print(si.content.rootFolder)
# >>> 'vim.Folder:group-d1'
# childEntityで1階層下がるとDatacenterが取得できる
print(si.content.rootFolder.childEntity)
# >>> (ManagedObject) [
# 'vim.Datacenter:datacenter-3'
# ]
# Datacenterを[0]で選び、その後ESXiを取得したいのでhostFolderを選択
print(si.content.rootFolder.childEntity[0].hostFolder)
# >>> 'vim.Folder:group-h5'
# hostFolderから1階層下がるとClusterが取得できた。(各vCenterのツリーに依存する)
print(si.content.rootFolder.childEntity[0].hostFolder.childEntity)
# >>>(ManagedObject) [
# 'vim.ClusterComputeResource:domain-c10',
# 'vim.ClusterComputeResource:domain-c8'
# ]
# moid(domain-c10)では分かりにくいので、<object>.nameで名前をprint (MOBにはnameも併記されているので分かりやすい。)
for cluster in si.content.rootFolder.childEntity[0].hostFolder.childEntity:
print(f"{cluster}:{cluster.name}")
# >>>'vim.ClusterComputeResource:domain-c10':v_cluster
# >>>'vim.ClusterComputeResource:domain-c8':p_cluster
ここからv_cluster
内のv10-nesxi-01.lab.local
を取得します。
# clusterを[0]で選んで、その中のhostを表示する
print(si.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host)
# >>> (ManagedObject) [
# 'vim.HostSystem:host-40',
# 'vim.HostSystem:host-43',
# 'vim.HostSystem:host-45'
# ]
# 同様にnameを表示
for host in si.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host:
print(f"{host}:{host.name}")
# >>>'vim.HostSystem:host-40':v10-nesxi-01.lab.local
# >>>'vim.HostSystem:host-43':v10-nesxi-02.lab.local
# >>>'vim.HostSystem:host-45':v10-nesxi-03.lab.local
# 取得したいhostを選んで、hostオブジェクトの取得完了
host = si.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0]
print(host)
# >>>'vim.HostSystem:host-40'
7. おわりに #
pyvmomiの基礎である、vCenterへの接続、任意のオブジェクトの取得方法は分かりましたでしょうか?
について解説します。
またMOBの構造が複雑であるため、pyvmomiでも階層構造を地道に探索してオブジェクトの取得をするのが大変でした。更に特定のオブジェクトを取得するのではなく、状況に応じて動的に探す場合にはこの手法が使えません。
こちらも実用的な解決策があるので第5回で紹介したいと思います。