vCenter Server のコンテンツライブラリにデータストアから直接 ISO ファイルをインポートする

追記: PowerCLI 12.1 で正式サポート

PowerCLI 12.1 がリリースされました。このバージョンから、New-ContentLibraryItem コマンドレットに引数 -Uri が追加され、ds:// スキーマによるデータストアからの直接のアップロードが正式にサポートされています。

The Uri, FileName, and SslThumbprint parameters have been added to the New-ContentLibraryItem cmdlet to allow uploading files from the Internet or datastore URLs.

PowerCLI Change Log

1 ファイル 1 行でアップロードできます。

PS> New-ContentLibraryItem -ContentLibrary ISO -Name rhel-8.2-x86_64-dvd.iso -FileName rhel-8.2-x86_64-dvd.iso -Uri ((Get-Datastore local-ds02).ExtensionData.Info.Url + "iso/rhel-8.2-x86_64-dvd.iso")               
Name                           ContentLibrary
----                           --------------
rhel-8.2-x86_64-dvd.iso        ISO

簡単ですね!

以下、元のエントリの内容は要らない子になってしまいましたが、残しておきます。

やりたかったこと

つまり、

  • データストアに直接保存しているたくさんの ISO ファイル
  • どうにかして コンテンツライブラリに簡単にインポートしたい

のです。

でも、コンテンツライブラリは、

  • ローカルファイルのアップロード
  • HTTP でのどこかからのダウンロード

のどちらかでしかインポートできないようで、愚直にやろうとすると、いちどローカルに全部ダウンロードして、それを再度アップロード することになります。

が、もちろん、これは数が多いと相当つらいので、強引でもいいからどうにかしてラクをできないかなあ、という話です。

解決策: データストアから HTTP でダウンロードさせる

PowerCLI スクリプトでの実装

簡単な PowerCLI の関数、Import-ContentLibraryItemFromDatastore を作りました。

こんな感じで、データストア上のファイルのパスと認証情報を渡すと、どうにかしてくれます。

> Import-ContentLibraryItemFromDatastore -Username temporary-user-01@vsphere.local -Password my-password -Item vmstore:\sandbox-dc01\sandbox-ds01\ISO -DestinationLibraryName "ISO Images"

Creating Sample_ISO_File.iso ...
Creating Update Session for Sample_ISO_File.iso ...
Pulling File Sample_ISO_File.iso from Datastore ...
  Waiting for Transfer ...
  Transferring ... 29570480 of 367654912 bytes
  Transferring ... 91598704 of 367654912 bytes
  Transferring ... 154513184 of 367654912 bytes
  Transferring ... 215776424 of 367654912 bytes
  Transferring ... 271944344 of 367654912 bytes
  Transferring ... 322272864 of 367654912 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...

トラフィックは、データストアを参照できる ESXi からいちど vCenter Server を経由して、再度 ESXi に流れてコンテンツライブラリのバックエンドのデータストアに書き込まれます。オーバヘッドはそれなりにあるものの、ローカルを経由させるよりは圧倒的に効率的…… なはずです。

-Item では、PowerCLI で接続すると利用できる vmstore:\ 表記で目的のファイルのパスを指定します。ファイルを指定した場合はそのファイル、ディレクトリを指定した場合は配下のファイルすべて、さらに -Recurse スイッチを追加した場合は再帰で取り込み対象が検索されます。ただし、現在では対象になるのは ISO ファイルのみ です。

後述しますが、-Username-Password は、内部でプレーンテキストで利用 されます。この影響で、各種ログなどにプレーンテキストで認証情報が残る 可能性があり、よって、利用する場合は 一時的な専用のユーザを作る ほうがよいでしょう。

詳しい実装は GitHub のリポジトリ を参照してください。

インポート後も、元の ISO ファイルは元のデータストア上に残るので、必要に応じて掃除をします。

PowerCLI スクリプトの利用例

例えば、次の 2 つの ISO ファイルをインポートしたいとします。

PS > Get-ChildItem vmstore:\kuro-dc01\local-ds01\ISO | Select Name, ItemType, Length

Name                      ItemType    Length
----                      --------    ------
Sample_ISO_File_1.iso IsoImageFile 367654912
Sample_ISO_File_2.iso IsoImageFile  88188928

作業前なので、コンテンツライブラリは空っぽです。

PS > Get-ContentLibraryItem -ContentLibrary "ISO Images"
PS >

作った関数でインポートさせます。事前に Connect-VIServerConnect-CisServer(どちらも接続先は vCenter Server)はしておきます。

PS > Import-ContentLibraryItemFromDatastore -Username username@vsphere.local -Password my-secure-password -Item vmstore:\kuro-dc01\local-ds01\ISO -DestinationLibraryName "ISO Images"
Creating Sample_ISO_File_1.iso ...
Creating Update Session for Sample_ISO_File_1.iso ...
Pulling File Sample_ISO_File_1.iso from Datastore ...
  Waiting for Transfer ...
  Waiting for Transfer ...
  Transferring ... 32245264 of 367654912 bytes
  Transferring ... 92454328 of 367654912 bytes
  Transferring ... 154309064 of 367654912 bytes
  Transferring ... 210416392 of 367654912 bytes
  Transferring ... 280139640 of 367654912 bytes
  Transferring ... 336237712 of 367654912 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...
Creating Sample_ISO_File_2.iso ...
Creating Update Session for Sample_ISO_File_2.iso ...
Pulling File Sample_ISO_File_2.iso from Datastore ...
  Waiting for Transfer ...
  Transferring ... 26515392 of 88188928 bytes
  Transferring ... 88188928 of 88188928 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...

インポートされました。

PS > Get-ContentLibraryItem -ContentLibrary "ISO Images"

Name                           ContentLibrary                 ItemType                       SizeGB
----                           --------------                 --------                       ------
Sample_ISO_File_1              ISO Images                     iso                            0.342
Sample_ISO_File_2              ISO Images                     iso                            0.082

仮想マシンからもマウントできます。

確認できたら、元のファイルを消して完了です。

PS > Remove-Item vmstore:\kuro-dc01\local-ds01\ISO -Recurse

仕組みと手作業で行うときの手順

コンテンツライブラリは、HTTP で公開されているコンテンツならインポートさせられるので、つまり、データストアの中身に vCenter Server が HTTP でアクセスできればよい わけです。

そして、vCenter Server も ESXi も、実は vSphere Web Service API により、ブラウザでデータストアにアクセスできます。vSphere Client の、ログイン画面の手前の右上のアレです。

つまり、データストアの任意のファイルに HTTP でアクセスできる ということです。

実際に掘っていき、目的の ISO ファイルを確認します。

このファイルの URL を確認すると、次のような URL が得られます。これが、ISO ファイルのダウンロード用の URL です。URL の書式の詳細はガイドに記載 があります。

  • https://kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01

ただし、この URL へのアクセスには認証が必要です。実際、例えば vCSA から wget でアクセスしようとすると、401 が返ります。

root@record [ ~ ]# wget 'https://kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01' -O Sample_ISO_File_1.iso
--2020-08-09 00:29:57--  https://kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01
Resolving kuro-vcs01.krkb.lab... 192.168.0.201
Connecting to kuro-vcs01.krkb.lab|192.168.0.201|:443... connected.
HTTP request sent, awaiting response... 401 Unauthorized

Username/Password Authentication Failed.

が、BASIC 認証なので、URL にユーザ名とパスワードを含めて しまえば、実はアクセスできます。

URL に BASIC 認証の情報を含めるには、

  • https://<ユーザ名>:<パスワード>@example.com/

とするだけです。ただし、ユーザ名の @%40 にエンコードします。よって、今回の URL であれば、

  • https://username%40vsphere.local:my-secure-password@kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01

とすればアクセスできます。

root@record [ ~ ]# wget 'https://username%40vsphere.local:my-secure-password@kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01' -O Sample_ISO_File_1.iso
--2020-08-09 00:30:21--  https://username%40vsphere.local:*password*@kuro-vcs01.krkb.lab/folder/ISO/Sample_ISO_File_1.iso?dcPath=kuro-dc01&dsName=local-ds01
Resolving kuro-vcs01.krkb.lab... 192.168.0.201
Connecting to kuro-vcs01.krkb.lab|192.168.0.201|:443... connected.
HTTP request sent, awaiting response... 401 Unauthorized
Authentication selected: Basic realm="VMware HTTP server"
Reusing existing connection to kuro-vcs01.krkb.lab:443.
HTTP request sent, awaiting response... 200 OK
Length: 367654912 (351M) [application/octet-stream]
Saving to: ‘Sample_ISO_File_1.iso’

Sample_ISO_File_1.iso                         100%[=================================================================================================>] 350.62M  69.8MB/s    in 4.8s

2020-08-09 00:30:26 (72.8 MB/s) - ‘Sample_ISO_File_1.iso’ saved [367654912/367654912]

よって、コンテンツライブラリのインポートソースとして、このような認証情報を含めた URL を指定することで、vCenter Server が直接 vCenter Server(や ESXi)からデータストアのコンテンツに HTTP でアクセスでき、結果として、ほぼ直接のインポートが成功します。

先述のスクリプトは、このような URL の組み立てや、HTTP ソースからのインポートを自動で行わせているだけです。

試したけどダメだった例

PowerCLI で vmstore:// 指定

PowerCLI でもコンテンツライブラリはいじれるようになっていて、組み込みのコマンドレットの New-ContentLibraryItem でコンテンツライブラリにファイルを追加できます。

ちまちまとコーディングをせずとも、これが使えるのがどう考えてもいちばん楽なので、安直な発想で Files の指定をこねくり回しました。

が、

  • Filesvmstore:\ のパスを直接書く
    • New-ContentLibraryItem : パラメーター 'Files' の引数変換を処理できません。指定されたパスのフォーマットはサポートされていません。 のエラー
  • New-PSDrive でデータストアにドライブ文字(V:\ など)を割り当ててFiles には V:\ のパスを書く
    • New-PSDrive -Name "V" -PSProvider VimDatastore -Root "\" -Location (Get-Datastore local-ds01) など
    • New-ContentLibraryItem : パラメーター 'Files' の引数変換を処理できません。Supplied path ('V:\ISO\Sample_ISO_File_1.iso') must exist. のエラー

で、いずれもダメでした。

PowerCLI で https://ds:// 指定

続けて、認証情報を埋め込んだ URL や ds://New-ContentLibraryItem に渡してみましたが、いずれもダメでした。

  • Files に認証情報を含んだ URL を指定
    • Unable to transform value 'https://...' into path. のエラー
  • Filesds:// で始まるパスを指定
    • 指定されたパスのフォーマットはサポートされていません。 のエラー

vSphere Automation API で ds:// 指定

ネイティブのコマンドレットが使えないことが分かったので、Get-CisService で Automation API を呼び出して使う作戦に変更しました。

コンテンツライブラリへのインポートは、Automation API では content.item.updatesession.fileadd を使いますが、このときにリクエストに含める FileAddSpec を見ると、source_endpointItemTransferEndpoint)の uri には、データストア内のコンテンツを示す ds:// スキーマが使えるように見えます。

Transfer endpoint URI. The supported URI schemes are: http, https, and ds. An endpoint URI with the ds scheme specifies the location of the file on the datastore. The format of the datastore URI is:
ds:///vmfs/volumes/uuid/path
When the transfer endpoint is a datastore location, the server can import the file directly from the storage backing without the overhead of streaming over HTTP.

ItemTransferEndpoint

URL にパスワードを埋め込むなどというお行儀の悪い方法より、これが使えるならこの方が良いに決まっているので、最初はこれを使うつもりでした。

ds:// 表記で組んでみると、エラーもなく動くし、転送タスクも流れるし、一見インポートできたかのようにはなりました。

PS > Import-ContentLibraryItemFromDatastore -Username username@vsphere.local -Password my-secure-password -Item vmstore:\kuro-dc01\local-ds01\ISO -DestinationLibraryName "ISO Images"
Creating Sample_ISO_File_1.iso ...
Creating Update Session for Sample_ISO_File_1.iso ...
Pulling File Sample_ISO_File_1.iso from Datastore ...
  Waiting for Transfer ...
  Transferring ... 0 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Transferring ... 7372 of 73728 bytes
  Completed.
Completing the Session ...
  Waiting for Complete ...
  Completed.
Deleting the Session ...

が、

  • API が返すファイルサイズが明らかにおかしい(上の例では、300 MB くらいのファイルなのに 70 KB 程度に見える)
  • インポートされたコンテンツライブラリ上のファイルが 4 KB に見える

な状態が抜け出せず、size プロパティを指定しても打破できず、ファイル自体もまともに使えないものにしかならなかったので、ダメでした。

おわりに

いろいろ試して最終的にはどうにかしたものの、そもそも、データストアからの直接のインポートは、もはや普通にできてしかるべきなのではという気がすごくしています。

実際、フォーラムを見ると、ちらほらと『できないの?』な質問はあるようです。

いずれも解決策は書かれていないので、しかたなく今回のような(あまりきれいではない)実装に至ったわけですが、公式の機能追加を待ちたいですね。

とはいえ、ホームユース程度であればこれで充分で、もともとやりたかった目の前の課題(大量のデータストア上の ISO をコンテンツライブラリに突っ込む)にはひとまず対応できそうです。

@kurokobo

くろいです。ギターアンサンブルやら音響やらがフィールドの IT やさんなアルトギター弾き。たまこう 48 期ぎたさん、SFC '07 おんぞう、新日本ギターアンサンブル、Rubinetto。今は野良気味。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です