スポンサーリンク

vmrun.exeで,仮想マシンの操作をバッチから自動化しよう (VMWare Server 2で,WindowsからLinuxをOSごと自動操作)

アプリケーション開発において,あらゆるテスト作業を自動化してゆくと,以下のような壁に突き当たる。

  • OS内の「環境の大変化」をテストしたい。例えば「OSの破壊」とか。(でも,後始末や再現が大変・・・)
  • Windowsから,Linuxを自動操作したい。(でも,つなげ方がわからない・・・)
  • 複数のマシンにまたがった操作を回帰テストしたい。(でも,PCは1台しかない・・・)
  • OSの「電源ON/OFF操作」を自動テストしたい。(でも,ハードの操作は簡単に自動化できない・・・)

VMWare Server 2 で vmrun.exe を使えば,これらはすべて無料で可能。

手元には,Windowsマシンが1台あればよい。

【早く】VMware Server 2【移行すべき】
http://blog.livedoor.jp/u_26/archives...

  • VMWare Serverは2になってWeb UIが導入されGUI化したが,CUIからも制御可能


技術的雑談-Windows上のVMWareServer2.0内のVMをコマンドラインで操作する
http://www.himajin2001.com/wiki.cgi?p...


vmrunのコマンド一覧
http://sites.google.com/site/xisite/H...


仮想化技術は,ITサービスの運用コストを削減するために昨今非常に多く用いられるようになった。


この同じ技術を,システム開発プロセスの自動化にも有効活用することができる。


1つのOSを単なる1つの「ファイル」として扱う事が可能になれば,「マシンの破壊」すら自動回帰テストできる,というわけだ。



以下では,vmrun.exeを呼び出すバッチのサンプルコードを掲載。


仮想マシンを自動操作して結果を調べるサンプルコード

環境は,

  • Host OS: Windows XP
  • Guest OS: CentOS

を想定。

また,仮想マシン内に「VMWare Tools」がインストールされている必要がある。
インストール手順は,この記事の末尾に記載した。



スクリプトの流れ:

  1. クリーンなLinux環境を準備する。(=試験環境を整える。)これには,仮想マシンのスナップショットを使う。
  2. Windowsマシンから,Linux仮想マシンへ,何らかのスクリプトを送る。(=試験対象プログラム。試験場の中で爆発させる爆弾のようなもの。)
  3. Linux仮想マシン内で,スクリプトを実行する。
  4. 実行結果を取得し,閲覧する。

以下がそのコード。



ゲストOSでスクリプト実行.bat

@rem ---------- VMWare Server 2 のインストール情報 ----------
@set SDKPATH=https://localhost:8333/sdk
@set VMROOT=C:\Program Files\VMWare\VMWare Server

@rem ---------- ホストOS側の設定情報 ----------
@set HOSTUSER=「WINDOWSのユーザ名」
@set HOSTPASS=「WINDOWSのパスワード」

@rem ---------- ゲストOS側の設定情報 ----------
@set GUESTUSER=「Linuxのユーザ名」
@set GUESTPASS=「Linuxのパスワード」
@set GUESTVMX="[standard] hoge/hoge.vmx"


@rem ---------- 処理 ここから ----------



@rem ---------- 事前準備 ----------

@echo ホスト内でvmrun.exeの存在するディレクトリに移動します。
@c:
@cd %VMROOT%
@cd

@echo VMWare Server 2 のSDKに接続可能かどうか確認します。
@netsh diag connect iphost localhost 8333



@rem ---------- クリーンなLinux環境を作成 ----------

@echo ゲストOSをスナップショットに戻します。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% ^
  revertToSnapshot %GUESTVMX%

@echo ゲストOSの電源をONします。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% ^
  start %GUESTVMX%

@echo 電源ONが正常に完了したのを確認するために,現在起動中の仮想マシンを一覧表示:
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% ^
  list



@rem ---------- Linux環境でスクリプトを準備 ----------

@echo ホストOSからゲストOSに,実行用スクリプトの資材をコピーします。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  copyFileFromHostToGuest %GUESTVMX% ^
  "C:\\shizai.tar.gz" ^
  "/tmp/shizai.tar.gz"

@echo コピーの正常終了を確認するために,コピー先ディレクトリ内のファイルを一覧表示:
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  listDirectoryInGuest %GUESTVMX% ^
  "/tmp/"

@echo ゲストOSで,実行用スクリプトの資材を展開(解凍)します。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  runProgramInGuest %GUESTVMX% ^
  "/bin/tar" ^
  -xvzf /tmp/shizai.tar.gz -C /tmp

@echo 展開の正常終了を確認するために,実行対象スクリプトの存在を判定:
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  fileExistsInGuest %GUESTVMX% ^
  /tmp/target.sh



@rem ---------- Linux環境でスクリプトを実行 ----------

@echo ゲストOSで,スクリプトを実行します。実行結果はログにリダイレクトします。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  runProgramInGuest %GUESTVMX% ^
  "/bin/sh" ^
  -c "sh /tmp/target.sh > /tmp/sh_log.txt 2>&1"

@echo ゲストOS内でのスクリプト実行が終了しました。ログを取得します。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  copyFileFromGuestToHost %GUESTVMX% ^
  "/tmp/sh_log.txt" ^
  "C:\\Documents and Settings\\%HOSTUSER%\\デスクトップ\\sh_log.txt"

@echo スクリプト実行の証跡として,ゲストOS内のスクリーンショットを取得します。
@vmrun -T server -h %SDKPATH% -u %HOSTUSER% -p %HOSTPASS% -gu %GUESTUSER% -gp %GUESTPASS% ^
  captureScreen %GUESTVMX% ^
  "C:\\cap.png"

@echo 取得したログの内容を表示します。
@pause
more "C:\\Documents and Settings\\%HOSTUSER%\\デスクトップ\\sh_log.txt"



@rem ---------- 終了 ----------

@echo バッチファイルの実行を終了します。
@pause

内容についての参考URL:

ポートのリッスン状態を調査する
http://www.atmarkit.co.jp/fwin2k/win2...

  • サーバの死活監視の際,pingコマンドではポートを指定できない。
  • 特定のポートが開いているかどうか確認するには,telnetないしnetshコマンドを利用する。
  • ここでは,8333番ポートの状況(つまり,VMWare Server SDKが利用可能かどうか)を調べている。


バッチファイル ファイル内で改行したい
http://okwave.jp/qa/q4217665.html

  • 行末を「^」(キャレット)で終えればよい


エラー出力を標準出力にマージする
http://flex.ee.uec.ac.jp/texi/sh/node...

  • 標準出力の記録とエラー履歴を一緒に取る
    • $ command >foo 2>&1
    • >& の働きは、左側に書かれたファイルディスクリプタの出力を右側に書かれたファイルディスクリプタに変更すること


cdの直前にc:と書いてある理由:

  • このバッチがDドライブで実行されたら,Cドライブに直接cdすることはできないから。
    • Cドライブにいる時に cd d: は無効。
    • /dオプションを付けた cd /d d: は有効なのでそれでもいい

仮想マシンを指定する方法・・・データストアパスについて:

VMware server で vmrunがうまく走らない
http://d.hatena.ne.jp/hon53/20090915/...

  • VMware Workstationだと,vmrunで仮想マシンを指定する際,VMXファイルのファイルパスを使える。
  • VMware Serverだと,vmrunで仮想マシンを指定する際,VMXファイルの「データストアパス」を使う必要がある。
  • 各仮想マシンの管理画面を開いてから,右側の「Commands」セクションの中の「Configure VM」をクリックすれば「Virtual Machine Configuration File」の項目にデータストアパスが表示される。これをコピペすればよい。
  • VMのWeb管理画面のトップの「Datastores」の見出し内を見れば,vmxの存在するディレクトリパスが [データストア名] で置き換わっているのがわかる。


各コマンドを走らせるたびに,毎回いちいち「ファイルの存在確認」とか「ディレクトリ内の一覧表示」をしている理由:

  • ゲストOS側で普通にコマンドラインからコマンドを実行した場合,各コマンドの実行結果は,コンソール上でリアルタイムに出力され確認することが可能。
  • しかし,vmrunからコマンドを実行した場合,コンソール出力を直接確認することができない。
  • なので,vmrunの組み込み判定コマンドを使ったり,リダイレクトで実行結果をテキストに出力したりして,間接的に実行結果を確かめる。


runProgramInGuestとかrunScriptInGuestを使う際の注意点:

  • コマンドラインから普通に実行するときとは,PATHが異なったりする。PATHをあてにせず,フルパスで書くこと。
  • 例えば,シェルスクリプト内で「ruby」と書いてあるだけだと,runProgramInGuest経由でそのシェルを叩いた時にエラーになる。ちゃんと「/usr/local/bin/ruby」のように記述しておけば安心。


captureScreenについて:

  • 仮想マシン上で表示されているのがCUIの画面であっても,画面キャプチャを取得できる。という点がすごい。
  • これは,バッチから画面キャプチャをするための強力な方法の一つだ。OSの種類に制限がない。それに仮想デバイスなので,モニタに出力される映像が直接取得できる。

画面のスクリーンショットを,Excelブック内に自動的に保存するバッチ
http://language-and-engineering.hatenablog.jp/entry/20100425/p1

  • VBAを使う方法


画面をコマンドラインからキャプチャする方法 (WSHバッチでPrintScreen)
http://language-and-engineering.hatenablog.jp/entry/20081121/1227203100

  • ms paintを使う方法


もし,vmrunの操作を共通モジュール化してbatとして保存したい場合は,
親batで環境変数を定義し,子batをcallすれば,
子bat内で親batの変数値を利用して処理を実行できる。

callのパイプ処理で環境変数への代入が消滅してしまう
http://fpcu.on.coocan.jp/dosvcmd/bbs/...

  • 親batから子batをcallした場合,環境変数は引き継がれる。子での変更は親にも影響を与える。しかし,子をcallする行でパイプ呼び出しすると,別プロセスみたいな扱いになり,子内での変更が親に影響を与えない。

補足(1)VMWare Host Agent サービスについて

上記のバッチを実行する際に,まだホスト側でVMが立ち上がっていない場合がある。


事前にホスト側でVMを立ち上げておくためのバッチ:


VM起動.bat

net stop "VMWare Host Agent"
net start "VMWare Host Agent"

起動中のサービスの一覧は

net start

とすれば表示できる。この出力結果の中に,「VMWare Host Agent」が含まれていればOK。



参考:

VMware Server 2のWeb Accessにアクセスできない場合の対処
http://blog.mynet.co.jp/nakamoto/2008...


バッチファイルでWindows のサービスを再起動する方法
http://fdays.blogspot.com/2008/03/win...


net startについて
http://pckida.hp.infoseek.co.jp/msnet...


なおWindows Vista以降では,batファイルでサービス起動のためnet startしようとしても権限不足で拒否される。

わざわざ右クリック→管理者として実行 するのは面倒。

また,batファイルにはプロパティから管理者実行設定ができない。


そこで,batファイルにショートカットを作り,そのショートカットファイルのプロパティから,ショートカットタブ上で「管理者として実行」の設定をすればよい。

バッチファイルを管理者権限で
http://daiworks.asablo.jp/blog/2007/0...

補足(2)VMWare Toolsについて

仮想マシンの内部を自動操作するためには,

その仮想マシンにVMWare Toolsがインストールされている必要がある。


Web UIで対象仮想マシンの管理画面を開き,右側の「Status」のセクション内で,「VMWare Tools」がRunningとなっていれば,インストール済み。


インストールされていない場合は,下記の手順を参照。


VMWare Toolsインストール手順

  1. 対象仮想マシンの電源がOFFであることを確認する。
  2. Web UIで対象仮想マシンの管理画面を開き,右側の「Status」のセクション内で,「VMWare Tools」が「Tools Not Installed」となっていることを確認する。
  3. 対象仮想マシンの電源をONする。
  4. Web UIで対象仮想マシンの管理画面を開き,右側の「Status」のセクション内で,「VMWare Tools」が「Install VMWare Tools」というリンクになっていることを確認する。
  5. 前項のリンクを押下。出現するダイアログ上で「Install」をクリック。
  6. VMWare Toolsのインストール資材が同梱されたCDROMイメージが,対象仮想マシンのCDドライブに,仮想的に挿入される。
  7. ここからは,対象仮想マシンを,CUIで操作する。VMコンソール経由でもいいし,puttyなどのsshツール経由でもいい。
  8. 以下のコマンドを実行して,VMWare Toolsのインストール資材をローカルに展開。
    • mount /dev/hdc /media/cdrom
    • cd /media/cdrom
    • cp -p VMwareTools-7.7.5-156740.tar.gz /tmp/
    • cd /tmp
    • tar -xvzf VMwareTools-7.7.5-156740.tar.gz
    • cd vmware-tools-distrib/
    • ./vmware-install.pl
  9. vmware-install.plが聞いてくる質問は全部yes(エンターキー押下)
  10. Web UIで対象仮想マシンの管理画面を開き,右側の「Status」のセクション内で,「VMWare Tools」が「Running」となっていることを確認する。
  11. VMWare Toolsのインストール完了。

VMwareTools-7.7.5-156745.tar.gz の展開
http://d.hatena.ne.jp/Guernsey/200907...

ホストOS:Winsows、ゲストOS:Linux の場合のインストール方法
http://www.nurs.or.jp/~sugi/vmware.htm