IronPython による VirtualBox のインポート・エクスポート - COM API 使用
VirtualBox のインポート・エクスポート処理を IronPython から COM API を使って試してみました。
環境は以下の通りです。
- Windows用 VirtualBox-4.2.14-86644
- IronPython 2.7.3
ソースは http://github.com/fits/try_samples/tree/master/blog/20130707/
事前準備
まずは、VirtualBox の COM を tlbimp コマンドを使って .NET アセンブリへ変換しておきます。
tlbimp 実行例
>tlbimp %VBOX_INSTALL_PATH%\VBoxC.dll ・・・ TlbImp : Type library imported to VirtualBox.dll
多少 warning は出ますが、VirtualBox.dll の作成に成功します。
エクスポート処理
エクスポート処理は概ね下記のようになります。
- (1) 空の Appliance 作成
- (2) Appliance へ Export
- (3) Appliance をファイル出力
(2) で Export メソッドへ渡す第2引数の値が .vmdk ファイルの一部(xxx--disk1.vmdk の xxx)に使用されます。 (3) の Write メソッドで出力フォーマットと出力ファイル(.ovf か .ova)を指定するようになっています。なお、出力ファイルに相対パス指定すると %USERPROFILE% ディレクトリからの相対パスとなるようです。
IProgress の WaitForCompletion() に -1 を指定すると処理が完了するまで待機します。
vbox_export.py
# coding: utf-8 import sys if len(sys.argv) < 3: print "%s <machine name> <output file>" % sys.argv[0] sys.exit() import os import clr clr.AddReference("VirtualBox") from VirtualBox import * vb = VirtualBoxClass() # 仮想マシンの取得 mc = vb.FindMachine(sys.argv[1]) filePath = sys.argv[2] fileName = os.path.basename(filePath) fileNameBase, ext = os.path.splitext(fileName) # (1) 空の Appliance 作成 ap = vb.CreateAppliance() # (2) Appliance へ Export # "<第2引数の値>-disk1.vmdk" が作成される事になる des = mc.Export(ap, fileNameBase) print "export start" # (3) Appliance をファイル出力 pr = ap.Write("ovf-2.0", 0, filePath) # 処理の完了待ち pr.WaitForCompletion(-1) print "export end"
実行例1
> ipy64 vbox_export.py centos6.4 c:\temp\sample1.ova export start export end
sample1.ova が作成されます。
実行例2
> ipy64 vbox_export.py centos6.4 c:\temp\sample2.ovf export start export end
sample2.ovf と sample2-disk1.vmdk が作成されます。
インポート処理
インポート処理は概ね下記のようになります。
- (1) 空の Appliance 作成
- (2) OVF ファイルの読み込み
- (3) OVF の解釈とセットアップ
- (4) 仮想マシンの作成
(2) で相対パスを指定すると export と同様に %USERPROFILE% ディレクトリからの相対パスとなるようです。 (3) と (4) の間で IVirtualSystemDescription を使った設定情報(仮想マシン名など)の変更が可能なようですが(getDescription() と setFinalValues() を利用する模様)、IronPython 上で getDescription() を適切に使う方法が分からなかったので今回は断念しました。
なお、今回は importMachines の引数に空の配列を指定しています。型に Int32 を指定している点にご注意ください。(ImportOptions とするとエラーになります)
vbox_import.py
# coding: utf-8 import sys if len(sys.argv) < 2: print "%s <input file>" % sys.argv[0] sys.exit() import clr clr.AddReference("VirtualBox") from System import * from VirtualBox import * vb = VirtualBoxClass() # (1) 空の Appliance 作成 ap = vb.CreateAppliance() print "import start" # (2) OVF ファイルの読み込み pr = ap.read(sys.argv[1]) # 処理の完了待ち pr.WaitForCompletion(-1) # (3) OVF の解釈とセットアップ ap.interpret() # 空の配列作成 opts = Array.CreateInstance(Int32, 0) # (4) 仮想マシンの作成 pr2 = ap.importMachines(opts) # 処理の完了待ち pr2.WaitForCompletion(-1) print "import end"
実行例1
> ipy64 vbox_import.py c:\temp\sample1.ova import start import end
実行例2
> ipy64 vbox_import.py c:\temp\sample2.ovf import start ・・・ EnvironmentError: System.Runtime.InteropServices.COMException (0x800706BE): リモート プロシージャ コールに失敗しました。 (HRESULT からの例外: 0x800706BE) ・・・
.ovf ファイルのインポートは Windows用 VirtualBox-4.2.14 に問題があるため失敗します。( 前回参照 )
WSH によるエクスポート処理
最後に、JScript で同様のエクスポート処理を実装してみると下記のようになります。
vbox_export.js
var args = WScript.Arguments; if (args.Count() < 2) { WScript.Echo("<machine name> <output file>"); WScript.Quit(); } var vb = WScript.CreateObject("VirtualBox.VirtualBox"); var fs = WScript.CreateObject("Scripting.FileSystemObject"); var mc = vb.findMachine(args.Item(0)); var filePath = args.Item(1); var ap = vb.createAppliance(); var des = mc.Export(ap, fs.GetBaseName(filePath)); WScript.Echo("export start"); var prog = ap.write("ovf-2.0", false, filePath); prog.waitForCompletion(-1); WScript.Echo("export end");
実行例
> cscript vbox_export.js centos6.4 c:\temp\sample3.ova ・・・ export start export end