PowerCLIによるゲストOSへのファイル転送

# 概要

VMware ToolsがインストールされたゲストOSに対しては、PowerCLIの`Copy-VMGuestFile`コマンドレットでファイルを送受信できる。

# 詳細

VMware ToolsがインストールされたゲストOSに対しては、VMware Toolsを介してファイルの送受信ができる。このためのPowerCLIコマンドレットとして`Copy-VMGuestFile`が用意されている。

* [VMware PowerCLI Cmdlets Reference > Copy-VMGuestFile](http://pubs.vmware.com/vsphere-65/index.jsp#com.vmware.powercli.cmdletref.doc/Copy-VMGuestFile.html)

## Copy-VMGuestFileによるファイル転送

あらかじめvCenter/ESXiホストにログイン（`Connect-VIServer`）し、仮想マシンのオブジェクトを取得（`Get-VM`）しておく。同名の仮想マシンが複数ある場合、仮想マシン名でのGet-VMは複数のオブジェクトを返すので、ファイル転送先にしたい仮想マシンを特定しておくこと。

    PowerCLI C:\> Connect-VIServer -Server "myVCenter" -User "vCenterAdmin" -Password "vCenterPass"
    PowerCLI C:\> $vm = Get-VM -Name "ws2008r2-001"
    PowerCLI C:\> $vm
    Name                 PowerState Num CPUs MemoryGB
    ----                 ---------- -------- --------
    ws2008r2-001         PoweredOn  6        6.000

`Copy-VMGuestFile`コマンドレットで、ローカルファイルをゲストOSへ転送。`-LocalToGuest`スイッチを使う。

    PowerCLI C:\> $vm | Copy-VMGuestFile -LocalToGuest -Source "c:\temp\localfile.txt" -Destination "c:\temp" -GuestUser "GuestAdmin" -GuestPassword "GuestPass"

`Copy-VMGuestFile`コマンドレットで、ゲストOS上のファイルをローカルへ転送。`-GuestToLocal`スイッチを使う。

    PowerCLI C:\> $vm | Copy-VMGuestFile -GuestToLocal -Source "c:\temp\guestfile.txt" -Destination "c:\temp" -GuestUser "GuestAdmin" -GuestPassword "GuestPass"

送信と受信のどちらの転送でも、他に以下を指定する。

|オプション|引数|
|---|---|
|-Source|転送対象ファイルのフルパス|
|-Destination|転送先ディレクトリのフルパス|
|-GuestUser|ゲストOSアカウントのユーザー名|
|-GuestPassword|ゲストOSアカウントのパスワード|

## 必要な認証情報

PowerCLIによるファイルの転送には、以下の認証情報が必要になる。

* vSphereのアカウント。`Connect-VIserver`でvSpehreに接続する際に使用する。
* ゲストOSのアカウント。`Copy-VMGuestFile`でファイルを転送する際に使用する。

例えばvSphereのシステム管理者であっても、ゲストOSに対して自由にファイル操作をできることにはならない。ただし、仮想マシンがネットワーク経由で接続できない「ローカルな」「閉じた」状態の時でも、ゲストOSでログインが不要だったり、パスワードが設定されていないということはないようにしたい。

## ワイルドカードでの転送対象（Source）指定

転送対象の指定時、パスの末尾にのみワイルドカードを使用できる。ただしローカルへのファイル受信（`-GuestToLocal`）で、ゲストOS上の転送対象ファイルの指定時にワイルドカードを使用するには、vCenter Server 5.0以降であること。

> Wildcards are allowed only at the end of the source path. If you are copying files from the guest operating system of a virtual machine to a local directory, the Source parameter supports wildcards only on vCenter Server 5.0 and later. ([VMware PowerCLI Cmdlets Reference > Copy-VMGuestFile](http://pubs.vmware.com/vsphere-65/index.jsp#com.vmware.powercli.cmdletref.doc/Copy-VMGuestFile.html))

例えば、次のような指定になる。

    PowerCLI C:\> $vm | Copy-VMGuestFile -LocalToGuest -Source "c:\temp\installer.zip.*" -Destination "c:\temp" -GuestUser "GuestAdmin" -GuestPassword "GuestPass"

なおゲストへのファイル送信（`-LocalToGuest`）では、転送対象を`Get-Item`コマンドレットからパイプラインで受け取ることもできる様子。[VMware PowerCLI Cmdlets Reference > Copy-VMGuestFile](http://pubs.vmware.com/vsphere-65/index.jsp#com.vmware.powercli.cmdletref.doc/Copy-VMGuestFile.html)のExample2に以下の例があり、実際に動作した。

    $vm = Get-VM -Name VM
    Get-Item "c:\FolderToCopy\*.*" | Copy-VMGuestFile -Destination "c:\MyFolder" -VM $vm -LocalToGuest -GuestUser -GuestPassword pass2

## 相対パスでの転送対象（Source）/転送先（Destination）の指定

ゲストOS上のパス指定には、絶対パスを使用する。ローカルのパス指定には相対パスを使用できる。

> If the file is on a virtual machine, specifies the absolute file path. Relative file paths are supported only when copying files from a local storage. ([VMware PowerCLI Cmdlets Reference > Copy-VMGuestFile](http://pubs.vmware.com/vsphere-65/index.jsp#com.vmware.powercli.cmdletref.doc/Copy-VMGuestFile.html))

細かく言えば、次のようになる。

* 仮想マシンへのファイル送信（`-LocalToGuest`）では、`-Source`でのローカルパス指定で相対パスも使用できる。`-Destination`でのゲストOS上のパス指定ではフルパスを使用する。
* ローカルへのファイル受信（`-GuestToLocal`）では、`-Destination`でのローカルパス指定で相対パスも使用できる。`-Source`でのゲストOS上のパス指定ではフルパスを使用する。

## 転送先（Destination）のディレクトリ指定

`-Destination`による転送先としてディレクトリを指定する時には、`\`や`/`をパスの末尾につけて明示的にディレクトリであることを示すと間違いがない。末尾に`\`や`/`がない場合、以下のような動作をした。

* 指定されたパスが既存のディレクトリであれば、ディレクトリパスとみなされ、そのディレクトリ内に転送元のファイル名のままでファイルが転送された。
* 指定されたパスが存在しなければ、ファイルパスとみなされ、そのパスでファイルが転送された（ファイル名が変更された）。

## 既存ファイルの上書きと転送先ディレクトリの作成

以下のケースでは、`-Force`オプションを指定する。

* 既存ファイルに上書きしたい
* 転送先に指定したディレクトリを作成させたい

`-Force`オプションを指定する時は、特に「転送先のディレクトリ指定」に注意した方がよい。

## 大きなファイルの転送

大きなファイルの転送が、タイムアウトにより失敗することがある。この時は`-ToolsWaitSecs`オプションで、長めの転送待ち時間(秒数)を指定する。デフォルトでは20秒。なお、`-ToolsWaitSecs -1`のように、正ではない値を指定するとタイムアウトしない（無限に待つ）。

また'System.OutOfMemoryException'により失敗することがある。vmwareのコミュニティにも[関連スレッド](https://communities.vmware.com/thread/344569)があるが、解決はしてなさそうだった。メモリ8GBのPCから10.3GBのVMDKファイルを転送しようとした際にこの例外で失敗し、700MBに分割したところ転送に成功した。

# 備考

## Copy-VMGuestFileによるファイル転送が有用なケース

`Copy-VMGuestFile`コマンドレットの直接の通信相手は対象仮想マシンの稼働しているESXiホストになる。ESXiホストからゲストOSまではVMware Toolsを介したファイル転送が行われる。したがって、ローカル環境とゲストOS、ESXiホストの管理通信とゲストOSの間にネットワーク通信経路がない環境でも、ゲストOSにファイルを転送できる。

## vmrunコマンドについて

PowerCLI以外では、[VMware VIX](https://www.vmware.com/support/developer/vix-api/)に含まれる[vmrun](https://www.vmware.com/support/developer/vix-api/vix112_vmrun_command.pdf)コマンドでもこうしたことが可能だった。しかしVMware VIXは[vSphere 5.0以降でvSphere APIに統合されていく方向](https://www.vmware.com/support/developer/vix-api/guestOps50_technote.pdf)のため、可能な作業はPowerCLI等のvSphere APIを使用するツールを移行していく方がよいと思われる。

# 参考

* [VMware PowerCLI Documentation](https://www.vmware.com/support/developer/PowerCLI/)
* [VMware PowerCLI Cmdlets Reference > Copy-VMGuestFile](http://pubs.vmware.com/vsphere-65/index.jsp#com.vmware.powercli.cmdletref.doc/Copy-VMGuestFile.html)
* [Using vmrun to Control Virtual Machines](https://www.vmware.com/support/developer/vix-api/vix112_vmrun_command.pdf)

----

本ページ内容は作成者の個人的なメモです。内容を保証するものではありません。また作成者の所属組織等とは一切かかわりがありません。