はじめに
前回のエントリ で、vSphere に古くから実装されている API である vSphere Web Services API(SOAP API)の触り方を紹介しました。その中で、Virtual Infrastructure JSON API にひとことだけ触れています。
SOAP API を(広義の)REST API のように触れる Virtual Infrastructure JSON API も vCenter Server 8.0 U1 以降が必要で、まだまだ一般的ではありません。
vSphere Web Services API(SOAP API)の触り方 | kurokobo.com
Virtual Infrastructure JSON API(VI/JSON API)は、vCenter Server 8.0 U1 で追加された新しい API で、ひとことで雑に表現するなら、従来の SOAP API の REST API 版 です。
本エントリでは、まだ日本語ではほとんど情報がないこの新しい API について、実例とともに簡単に紹介します。
なお、vSphere の REST API といえば vSphere Automation API が一般的ですが、VI/JSON API はこれとはまったく別物 です。
目次
基本的な考え方
概要
Virtual Infrastructure JSON API(VI/JSON API)は、前述の通り、ひとことでは 従来の SOAP API の REST API 版 で、次の特徴を持ちます。
- SOAP API と同じエンドポイントを利用する
- SOAP API と同じ API が公開されている(後方互換性がある)
- XML ではなく JSON でやりとりする
- Cookie ではなく専用の HTTP ヘッダで認証する
- 管理対象オブジェクトのプロパティを直接参照できる(新機能、後述)
SOAP API と後方互換性がある ように設計されているため、従来の SOAP API を利用したクライアントが、ロジックを維持したまま REST API での操作に移行 する目的で利用できます。ただしこの場合は、お作法が REST API に変わるだけで、実行すべきメソッドやその順序、結果から拾うべき値などが SOAP API のときと変わるわけではない点には注意が必要です。この意味で、従来の SOAP API の操作に習熟することは、VI/JSON API を触る上でも重要です。
一方で、後述の実例で紹介しますが、管理対象オブジェクトのプロパティの取得 が PropertyCollector を使わずに直接 GET できる 点など、後発ならではの機能強化もされており、この点は VI/JSON API の明らかな強みと言えます。
実行イメージ
VI/JSON API の操作感は非常にシンプルで、雑にいうとイマドキです。
例えば、SOAP API で仮想マシンの電源を入れる 操作をしたい場合、VirtualMachine オブジェクトの PowerOnVM_Task
を実行 するため、curl では次のコマンドが必要でした(認証済みかつ管理対象オブジェクト ID は特定済みのものとしています)。
$ WSAPI_URL=https://kuro-vcs01.kurokobo.internal/sdk
$ curl \
-sX POST ${WSAPI_URL} \
-b ./cookies.txt \
-H 'content-type: text/xml; charset="utf-8"' \
-H 'soapaction: urn:vim25/8.0.2.0' \
-d @- << EOF
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<PowerOnVM_Task xmlns="urn:vim25">
<_this type="VirtualMachine">vm-14011</_this>
</PowerOnVM_Task>
</Body>
</Envelope>
EOF
同じ VirtualMachine オブジェクトの PowerOnVM_Task
の実行 を、今度は VI/JSON API で行う 場合、コマンドは次の通りです。この操作ではリクエストボディは空 です。
$ JSONAPI_URL=https://kuro-vcs01.kurokobo.internal/sdk/vim25/8.0.2.0/VirtualMachine/vm-14011/PowerOnVM_Task
$ curl \
-sX POST ${JSONAPI_URL} \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}"
両者を見比べると、与えているパラメータは同じ ですが、指定方法が異なっている ことが読み取れます。
- リクエストボディの XML で指定していた 操作対象やメソッド名 は URL で指定
VirtualMachine
、vm-14011
、PowerOnVM_Task
- リクエストヘッダで渡していたバージョン情報も URL で指定
8.0.2.0
- Cookie で渡していた 認証情報 は リクエストヘッダで指定
vmware-api-session-id
公式ドキュメント
Virtual Infrastructure JSON API に関する公式のドキュメントとして、リファレンスのほか、前回のエントリ でも紹介したプログラミングガイドの中に、8.0 U1 以降は VI/JSON API についての章が追加されています。
- vSphere Management SDK(関連ドキュメントの一覧)
- Virtual Infrastructure JSON API – API Reference
- vSphere Web Services SDK Programming Guide (8.0U2)
- vSphere Web Services SDK Programming Guide (8.0U2) – Client Applications Using the JSON Protocol
また、VI/JSON API が実装された当初、VMWARE {code} の公式ブログ でも紹介されていました。概要から実例まで紹介されており、併せて参考にできます。
- Introducing VI/JSON – a modern wire protocol for vSphere management – VMware {code}
- Automating vSphere Workflows with VI/JSON – VMware {code}
- Integrating VI/JSON in pyVmomi scripts – VMware {code}
- Read vCenter inventory using VI/JSON API – VMware {code}
参考: リクエスト URL の組み立て
VI/JSON API では、操作したい管理対象オブジェクトと実行したいメソッドは、URL で指定します。ガイドでも紹介 されていますが、構文は次の通りです。
https://[FQDN]/sdk/vim25/[バージョン]/[型]/[管理対象オブジェクト ID]/[メソッド]
これは、SOAP API の HTTP リクエスト中のそれぞれ以下に対応します。
POST /sdk HTTP/2
...
soapaction: urn:vim25/[バージョン]
...
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<[メソッド] xmlns="urn:vim25">
<_this type="[型]">[管理対象オブジェクト ID]</_this>
</[メソッド]>
...
</Body>
</Envelope>
参考: リクエストボディの組み立て
VI/JSON API では、メソッドに渡すパラメータをリクエストボディに JSON 形式で含めます。ガイドでも紹介 されています。
{
"<パラメータ名>": <値>
}
ただし、値が SOAP API の WSDL で定義されている型のオブジェクトの場合、都度 _typeName
キーで型名を明示します。
例えば、PropertyFilterSpec 型のプロパティ propSet
は、XML では次のように組み立てられます。
<propSet>
<type>VirtualMachine</type>
<pathSet>name</pathSet>
</propSet>
これを JSON で表すと次のようになります。リファレンス からプロパティ propSet
が PropertySpec 型のオブジェクトの配列であることがわかるため、配列 []
とし、_typeName
で PropertySpec
を与えます。
{
"propSet": [
{
"_typeName": "PropertySpec",
"type": "VirtualMachine",
"pathSet": ["name"]
}
]
}
すべてのオブジェクトを XML から JSON に手で書き換えていくのは非常に大変です。このため、リファレンスのオブジェクトやメソッドごとのページでも JSON の例が示されている ほか、XML と JSON を相互変換する Transcoder API も用意されています。Transcoder API の使い方は本エントリの末尾で紹介しています。
本エントリで紹介する実例
VI/JSON API を操作する実例として、前回のエントリ で紹介したシナリオのうち、仮想マシンの設定の取得 を取り上げます。ただし、VI/SOAP API の特性から、このシナリオは次の二つのパタンで実現できるため、それぞれ紹介します。
- 従来の SOAP API の操作をそのまま VI/JSON API に置き換える場合
- VI/JSON API のネイティブの方法を使う場合
いずれにせよ、認証してセッションを作成する操作 と 対象の管理対象オブジェクト ID を特定する操作 は必須のため、まずはこれを行います。
なお、以降の全ての例で次の変数は共通です。
$ JSONAPI_HOST="kuro-vcs01.kurokobo.internal"
$ JSONAPI_RELEASE="8.0.2.0"
前提 (1): 認証とセッションの作成
認証には SOAP API のときと同様に SessionManager の Login
を実行しますが、まずは SessionManager の特定が必要です。
SOAP API の手法に従う場合、ServiceInstance の RetrieveServiceContent
に POST して確認します。
$ JSONAPI_SI_MOID="ServiceInstance"
$ JSONAPI_SM_MOID=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
| jq -r .sessionManager.value \
| xargs -t0 \
)
$ echo "${JSONAPI_SM_MOID}"
SessionManager
VI/JSON API ネイティブの方法として、ServiceInstance の content
を GET することでも同様の結果が得られます。
$ JSONAPI_SI_MOID="ServiceInstance"
$ JSONAPI_SM_MOID=$( \
curl \
-sX GET \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/content \
| jq -r .sessionManager.value \
| xargs -t0 \
)
$ echo "${JSONAPI_SM_MOID}"
SessionManager
特定できた SessionManager の ID を URL で指定して、Login
を実行します。レスポンスヘッダで vmware-api-session-id
が返ってくるため、後続の操作に備えてこの値を保存します。
$ JSONAPI_USERNAME="wsapi@vsphere.local"
$ JSONAPI_PASSWORD="VMware123!"
$ JSONAPI_LOCALE="en_US"
$ JSONAPI_SESSION_ID=$( \
curl \
-siX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/SessionManager/${JSONAPI_SM_MOID}/Login \
-H "content-type: application/json" \
-d @- << EOF \
| grep "vmware-api-session-id" | tr -d "\r" | cut -d " " -f 2 \
| xargs -t0
{
"userName": "${JSONAPI_USERNAME}",
"password": "${JSONAPI_PASSWORD}",
"locale": "${JSONAPI_LOCALE}"
}
EOF
)
$ echo "${JSONAPI_SESSION_ID}"
61c2623dfc43bf7dc910205a57b50db9cb19a195
なお、ヘッダ vmware-api-session-id
は VI/JSON API ではなく vSphere Automation API(いわゆる REST API)でも利用していますが、セッション ID は API ごとに独立しているため、使いまわしはできません。
前提 (2): 操作する管理対象オブジェクトの特定
この流れは SOAP API のときと同様です。今回も仮想マシン kuro-exec01
の管理対象オブジェクト ID を調べるものとします。
まずは ViewManager の CreateContainerView
で ContainerView を作成します。
# ViewManager の ID の特定
$ JSONAPI_VIEWMANAGER_MOID=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
| jq -r .viewManager.value \
| xargs -t0 \
)
$ echo "${JSONAPI_VIEWMANAGER_MOID}"
ViewManager
# インベントリのルートフォルダの特定
$ JSONAPI_ROOT_FOLDER=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
| jq -r .rootFolder \
| xargs -t0 \
)
$ echo "${JSONAPI_ROOT_FOLDER}"
{
"_typeName": "ManagedObjectReference",
"value": "group-d1",
"type": "Folder"
}
# ContainerView の作成
$ JSONAPI_CONTAINER_VIEW=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ViewManager/${JSONAPI_VIEWMANAGER_MOID}/CreateContainerView \
-H "content-type: application/json" \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
-d @- << EOF \
| xargs -t0
{
"container": ${JSONAPI_ROOT_FOLDER},
"recursive": true,
"type": ["VirtualMachine"]
}
EOF
)
$ echo "${JSONAPI_CONTAINER_VIEW}"
{
"_typeName": "ManagedObjectReference",
"value": "session[5270677a-f371-0117-7df3-36c881fd1118]525d75e8-2e95-3187-449f-41bc9c47f780",
"type": "ContainerView"
}
PropertyCollector の RetrievePropertiesEx
を使用して仮想マシンの管理対象オブジェクト ID と名前の一覧を取得し、目的の仮想マシン kuro-exec01
の管理対象オブジェクト ID を特定します。以下の例では、レスポンスの JSON の中身をそのまま jq
に渡して、jq
の中で仮想マシンを検索しています。
# PropertyCollector の ID の特定
$ JSONAPI_PROPERTYCOLLECTOR_MOID=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ServiceInstance/${JSONAPI_SI_MOID}/RetrieveServiceContent \
| jq -r .propertyCollector.value \
| xargs -t0 \
)
$ echo "${JSONAPI_PROPERTYCOLLECTOR_MOID}"
propertyCollector
# 仮想マシンの ID と名前の一覧の取得
$ JSONAPI_TARGET_VM="kuro-exec01"
$ JSONAPI_VM_MOID=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/PropertyCollector/${JSONAPI_PROPERTYCOLLECTOR_MOID}/RetrievePropertiesEx \
-H "content-type: application/json" \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
-d @- << EOF \
| jq -r --arg VM "${JSONAPI_TARGET_VM}" '.objects[] | select (.propSet[].val._value == $VM) | .obj.value'
{
"specSet": [
{
"_typeName": "PropertyFilterSpec",
"propSet": [
{
"_typeName": "PropertySpec",
"type": "VirtualMachine",
"pathSet": ["name"]
}
],
"objectSet": [
{
"_typeName": "ObjectSpec",
"obj": ${JSONAPI_CONTAINER_VIEW},
"skip": true,
"selectSet": [
{
"_typeName": "TraversalSpec",
"type": "ContainerView",
"path": "view"
}
]
}
]
}
],
"options": {
"_typeName": "RetrieveOptions",
"maxObjects": 1000
}
}
EOF
)
$ echo "${JSONAPI_VM_MOID}"
vm-14011
使い終わった ContainerView は、ContainerView の DestroyView
で削除します。
$ JSONAPI_CONTAINER_VIEW_MOID_ENCODED=$(echo "${JSONAPI_CONTAINER_VIEW}" | jq -r ".value | @uri")
$ curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/ContainerView/${JSONAPI_CONTAINER_VIEW_MOID_ENCODED}/DestroyView \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}"
実例: 仮想マシンの設定を取得する(SOAP API 互換)
仮想マシンの設定のうち vmOpNotificationTimeout
の値を確認したいものとして、まずは従来の SOAP API を置き換える場合の実例です。
この場合は、PropertyCollector の RetrievePropertiesEx
を利用します。
$ JSONAPI_VM_OP_NOTIFICATION_TIMEOUT=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/PropertyCollector/${JSONAPI_PROPERTYCOLLECTOR_MOID}/RetrievePropertiesEx \
-H "content-type: application/json" \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
-d @- << EOF \
| jq -r .objects[].propSet[].val.vmOpNotificationTimeout
{
"specSet": [
{
"_typeName": "PropertyFilterSpec",
"propSet": [
{
"_typeName": "PropertySpec",
"type": "VirtualMachine",
"pathSet": ["config"]
}
],
"objectSet": [
{
"_typeName": "ObjectSpec",
"obj": {
"_typeName": "ManagedObjectReference",
"value": "${JSONAPI_VM_MOID}",
"type": "VirtualMachine"
},
"skip": false
}
]
}
],
"options": {
"_typeName": "RetrieveOptions"
}
}
EOF
)
$ echo "${JSONAPI_VM_OP_NOTIFICATION_TIMEOUT}"
300
実例: 仮想マシンの設定を取得する(VI/JSON API ネイティブ)
同じ設定を VI/JSON API ネイティブの方法で確認する場合、VirtualMachine の config
を GET するだけです。
$ JSONAPI_VM_OP_NOTIFICATION_TIMEOUT=$( \
curl \
-sX GET \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/VirtualMachine/${JSONAPI_VM_MOID}/config \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
| jq -r .vmOpNotificationTimeout
)
$ echo "${JSONAPI_VM_OP_NOTIFICATION_TIMEOUT}"
300
補足: XML と JSON の相互変換
SOAP API を VI/JSON API に置き換えていく際、XML を JSON に書き換えたり、逆に JSON を XML に書き換えたりする必要が生じます。
この目的で、オブジェクトの XML と JSON を相互に変換できる Transcoder API が 8.0 U2 で実装されました。
例えば、SOAP API の PropertyCollector オブジェクトの RetrievePropertiesEx
メソッド には、パラメータ specSet
として PropertyFilterSpec 型のオブジェクトを渡していました。XML では、次のハイライト部分(7-18 行)です。
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<RetrievePropertiesEx xmlns="urn:vim25">
<_this type="PropertyCollector">propertyCollector</_this>
<specSet>
<propSet>
<type>VirtualMachine</type>
<pathSet>name</pathSet>
</propSet>
<objectSet>
<obj type="ContainerView">session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4</obj>
<skip>true</skip>
<selectSet xmlns:XMLSchema-instance="http://www.w3.org/2001/XMLSchema-instance" XMLSchema-instance:type="TraversalSpec">
<type>ContainerView</type>
<path>view</path>
</selectSet>
</objectSet>
</specSet>
<options>
<maxObjects>1000</maxObjects>
</options>
</RetrievePropertiesEx>
</Body>
</Envelope>
この specSet
を Transcoder API で JSON に変換したいときは、次のリクエストを実行します。変換の方向をヘッダ content-type
と accept
で指定し、リクエストボディとして変換したい文字列を渡しています。変換元の型名は xsi:type
で明示します。レスポンスで変換された JSON 文字列が返ってきます。
$ JSONAPI_SPECSET_JSON=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/transcoder \
-H 'content-type: application/xml' \
-H 'accept: application/json' \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
-d @- << EOF
<obj versionId="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:vim25" xsi:type="PropertyFilterSpec">
<propSet>
<type>VirtualMachine</type>
<pathSet>name</pathSet>
</propSet>
<objectSet>
<obj type="ContainerView">session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4</obj>
<skip>true</skip>
<selectSet xmlns:XMLSchema-instance="http://www.w3.org/2001/XMLSchema-instance" XMLSchema-instance:type="TraversalSpec">
<type>ContainerView</type>
<path>view</path>
</selectSet>
</objectSet>
</obj>
EOF
)
$ echo "${JSONAPI_SPECSET_JSON}"
{
"_typeName": "PropertyFilterSpec",
"propSet": [
{
"_typeName": "PropertySpec",
"type": "VirtualMachine",
"pathSet": ["name"]
}
],
"objectSet": [
{
"_typeName": "ObjectSpec",
"obj": {
"_typeName": "ManagedObjectReference",
"value": "session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4",
"type": "ContainerView"
},
"skip": true,
"selectSet": [
{
"_typeName": "TraversalSpec",
"type": "ContainerView",
"path": "view"
}
]
}
]
}
逆に JSON を変換して XML にもできます。例として、上の例で返ってきた JSON をそのまま渡して XML にします(変換の方向が逆なので、content-type
と accept
の値を入れ替えています)。
$ JSONAPI_SPECSET_XML=$( \
curl \
-sX POST \
https://${JSONAPI_HOST}/sdk/vim25/${JSONAPI_RELEASE}/transcoder \
-H "content-type: application/json" \
-H 'accept: application/xml' \
-H "vmware-api-session-id: ${JSONAPI_SESSION_ID}" \
-d @- << EOF
{
"_typeName": "PropertyFilterSpec",
"propSet": [
{
"_typeName": "PropertySpec",
"type": "VirtualMachine",
"pathSet": ["name"]
}
],
"objectSet": [
{
"_typeName": "ObjectSpec",
"obj": {
"_typeName": "ManagedObjectReference",
"value": "session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4",
"type": "ContainerView"
},
"skip": true,
"selectSet": [
{
"_typeName": "TraversalSpec",
"type": "ContainerView",
"path": "view"
}
]
}
]
}
EOF
)
$ echo "${JSONAPI_SPECSET_XML}" | xmllint --format -
<?xml version="1.0"?>
<obj xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:vim25" versionId="8.0.2.0" xsi:type="PropertyFilterSpec">
<propSet>
<type>VirtualMachine</type>
<pathSet>name</pathSet>
</propSet>
<objectSet>
<obj type="ContainerView">session[527102d1-b0db-1b07-ab00-e545fc76ca41]5253a3b5-b708-89eb-9c36-fec2253787f4</obj>
<skip>true</skip>
<selectSet xsi:type="TraversalSpec">
<type>ContainerView</type>
<path>view</path>
</selectSet>
</objectSet>
</obj>
なお、Transcoder API の利用にはコマンド例のとおり認証が必要ですが、SOAP API クライアントからの利用をしやすくするため、Transcoder API だけは SOAP API と同じ Cookie を利用した認証も許容されているようです。
補足: curl でヘッダを取り出すときの考慮点
curl に限定した余談です。
curl でレスポンスヘッダから値を拾うとき、-v
や -I
でヘッダを標準出力に吐かせてから grep
するパタンがよく使われますが、このとき、curl はサーバと送受信したヘッダをそのまま出力するようです。つまり、行末が CR+LF
になっています。
# レスポンスヘッダの content-type を拾う例
$ curl -sI --no-styled-output www.example.com \
| grep -i --color=never content-type
Content-Type: text/html; charset=UTF-8
# バイナリダンプすると行末に CR+LF(0x0d, 0x0a)があることがわかる
$ curl -sI --no-styled-output www.example.com \
| grep -i --color=never content-type \
| od -tx1z -Ax
000000 43 6f 6e 74 65 6e 74 2d 54 79 70 65 3a 20 74 65 >Content-Type: te<
000010 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 65 74 >xt/html; charset<
000020 3d 55 54 46 2d 38 0d 0a >=UTF-8..<
000028
このため、grep
後に単純に cut
や awk
で雑に値部分を抽出すると、行末の CR
も含まれてしまいます。
# awk で値部分を取り出して格納
$ HEADER=$( \
curl -sI --no-styled-output www.example.com \
| grep -i --color=never content-type \
| awk -F ': ' '{print $2}' \
)
# それっぽい切り出しができていそうに見える
$ echo "${HEADER}"
text/html; charset=UTF-8
# 実際には末尾に CR(0x0d)が残っている
$ echo -n "${HEADER}" | od -tx1z -Ax
000000 74 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 >text/html; chars<
000010 65 74 3d 55 54 46 2d 38 0d >et=UTF-8.<
000019
使途次第では無視できますが、少なくとも VI/JSON API では、ヘッダに埋め込むセッション ID の末尾に CR
が残った状態でリクエストしても正常に処理されず、レスポンスが得られません。
このため、本エントリのコマンド例では、セッション ID を取り出すコマンドの grep
のあとに tr -d "\r"
を入れて、CR
を明示的に取り除いています。
# CR を取り除く
$ HEADER=$( \
curl -sI --no-styled-output www.example.com \
| grep -i --color=never content-type \
| tr -d "\r" \
| awk -F ': ' '{print $2}' \
)
# 末尾の CR がなくなる
$ echo -n "${HEADER}" | od -tx1z -Ax
000000 74 65 78 74 2f 68 74 6d 6c 3b 20 63 68 61 72 73 >text/html; chars<
000010 65 74 3d 55 54 46 2d 38 >et=UTF-8<
000018
おわりに
VI/JSON API は、従来の SOAP API のクライアントを REST API ベースの実装に移行できるだけでなく、PropertyCollector を介さずに直接 GET できるオブジェクトが多数用意されており、少なくとも XML と格闘するよりは圧倒的に直感的に操作できます。
vCenter Server 8.0 U1 以降が必要にはなりますが、SOAP API の操作にハードルを感じている場合、VI/JSON API がよい代替手段となりそうです。
利用できるメソッドはリファレンスで一覧 できるので、おもしろそうなものをとにかく触ってみるのもたのしそうです。