目次
追記: 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-VIServer
と Connect-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
の指定をこねくり回しました。
が、
Files
にvmstore:\
のパスを直接書く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.
のエラー
Files
にds://
で始まるパスを指定指定されたパスのフォーマットはサポートされていません。
のエラー
vSphere Automation API で ds://
指定
ネイティブのコマンドレットが使えないことが分かったので、Get-CisService
で Automation API を呼び出して使う作戦に変更しました。
コンテンツライブラリへのインポートは、Automation API では content.item.updatesession.file
の add
を使いますが、このときにリクエストに含める FileAddSpec
を見ると、source_endpoint
(ItemTransferEndpoint
)の uri
には、データストア内のコンテンツを示す ds://
スキーマが使えるように見えます。
Transfer endpoint URI. The supported URI schemes are:
ItemTransferEndpointhttp
,https
, andds
. An endpoint URI with theds
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.
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
プロパティを指定しても打破できず、ファイル自体もまともに使えないものにしかならなかったので、ダメでした。
おわりに
いろいろ試して最終的にはどうにかしたものの、そもそも、データストアからの直接のインポートは、もはや普通にできてしかるべきなのではという気がすごくしています。
実際、フォーラムを見ると、ちらほらと『できないの?』な質問はあるようです。
- Upload ISOs to Content Library from a datastore.
- Content Library in version 6.5 working with ISO files already present on a datastore
- Is it possible to Move Datastore ISO files to content library ?
いずれも解決策は書かれていないので、しかたなく今回のような(あまりきれいではない)実装に至ったわけですが、公式の機能追加を待ちたいですね。
とはいえ、ホームユース程度であればこれで充分で、もともとやりたかった目の前の課題(大量のデータストア上の ISO をコンテンツライブラリに突っ込む)にはひとまず対応できそうです。