Windows 10 TP環境でVagrantと自作Hyper-V boxの扱いにハマっていた

先に結論を知りたい人のために書くと

Windows 10 TPとHyper-Vの組み合わせで既存のVagrant boxを使うことはできる。 が、現状Windows 10 TP上で自分で作ったboxは使うことができない。

エラー環境

自作のHyper-V向けVagrant boxを作っていたら vagrant upでエラーが出ていたから色々調査した。 最初はCore OSのboxの作りが悪いのかと思っていたら、既存のboxをカスタマイズ後エクスポートしてもエラーが出ていたので怪しいと踏んだ。

Vagrantのエラーメッセージ

$ vagrant up
Bringing machine 'default' up with 'hyperv' provider...
==> default: Verifying Hyper-V is enabled...
c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/config.rb:83:in `block in missing_interpolation_argument_handler': missing interpolation argument :name in "The box you're using with the Hyper-V provider ('%{name}')\nis invalid. A Hyper-V box should contain both a\n\"Virtual Machines\" and a \"Virtual Hard Disks\" folder that are\ncreated as part of exporting a Hyper-V machine.\n\nWithin these directories, Vagrant expects to find the\nvirtual machine configuration as well as the root hard disk.\n\nThe box you're attempting to use is missing one or both of\nthese directories or does not contain the files expected. Verify\nthat you added the correct box. If this problem persists,\nplease contact the creator of the box for assistance." ({:_key=>:box_invalid, :_namespace=>"vagrant_hyperv.errors"} given) (I18n::MissingInterpolationArgument)
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/interpolate/ruby.rb:29:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/interpolate/ruby.rb:29:in `block in interpolate_hash'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/interpolate/ruby.rb:21:in `gsub'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/interpolate/ruby.rb:21:in `interpolate_hash'

        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/interpolate/ruby.rb:17:in `interpolate'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/backend/base.rb:153:in `interpolate'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n/backend/base.rb:41:in `translate'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n.rb:157:in `block in translate'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n.rb:153:in `catch'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/i18n-0.6.11/lib/i18n.rb:153:in `translate'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/errors.rb:103:in `translate_error'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/errors.rb:72:in `initialize'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/plugins/providers/hyperv/action/import.rb:41:in `exception'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/plugins/providers/hyperv/action/import.rb:41:in `raise'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/plugins/providers/hyperv/action/import.rb:41:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:95:in `block in finalize_action'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/builder.rb:116:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/runner.rb:66:in `block in run'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/util/busy.rb:19:in `busy'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/runner.rb:66:in `run'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/builtin/call.rb:53:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/builtin/config_validate.rb:25:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/builtin/handle_box.rb:56:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/plugins/providers/hyperv/action/check_enabled.rb:18:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/warden.rb:34:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/builder.rb:116:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/runner.rb:66:in `block in run'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/util/busy.rb:19:in `busy'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/action/runner.rb:66:in `run'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/machine.rb:214:in `action_raw'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/machine.rb:191:in `block in action'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/environment.rb:516:in `lock'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/machine.rb:178:in `call'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/machine.rb:178:in `action'
        from c:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.7.2/lib/vagrant/batch_action.rb:82:in `block (2 levels) in run'

調査

  • Windows 8.1ではどうか
    • 既存のboxカスタマイズは問題なく動作

なので違う部分が何かあるということ。

boxのディレクトリ構造

hashicorp/precise64

/path/to/hashicorp-VAGRANTSLASH-precise64/1.1.0/hyperv
|--Vagrantfile
|--Virtual Hard Disks
|  |--precise64.vhdx
|--Virtual Machines
|  |--6C85D451-6B8B-410B-927C-8DE28E84DAD6.XML
|--metadata.json

自作box

/path/to/my-VAGRANTSLASH-trusty64/0/hyperv
|--Virtual Hard Disks
|  |--trusty64.vhdx
|--Virtual Machines
|  |--E8B4D4CB-B77A-40C9-8AEF-C2D72A92B807.VMRS
|  |--E8B4D4CB-B77A-40C9-8AEF-C2D72A92B807.vmcx
|--metadata.json

OSをアップデートしたとか仮想マシン名が違うということを除くと、違いは Virtual Machines 内の構成が変わっていること。

Windows 10でのHyper-Vの変更点

What's New in Hyper-V in Technical Preview

Virtual machines now have a new configuration file format which is designed to increase the efficiency of reading and writing virtual machine configuration data. It is also designed to reduce the potential for data corruption in the event of a storage failure. The new configuration files use the .VMCX extension for virtual machine configuration data and the .VMRS extension for runtime state data. 

The .VMCX file is a binary format, directly editing the .VMCX or .VMRS file is not supported.

Technical PreviewではHyper-Vの設定データが入っているファイルフォーマットを変更したようです。 VMCXファイルが仮想マシンの設定で、VMRSファイルが実行時の状態のデータフォーマットになっているみたいですね。

推測

VagrantではHyper-Vのboxファイルを登録する際にチェックしているのはVirtual Hard Disks、Virtual Machinesのディレクトリとmetadata.jsonがあるかのみ。 vagrant up時に現状ではXMLファイルを読みだして仮想マシンを設定していると思われる。 で、Windows 10 TPではファイルはopenしたけどバイナリだから必要なキーを読めずにエラーを出してるという感じかな。

まとめ

今のところWindows 10 TPでHyper-V用のbox作るのは無理な気がする。 どうしてもWindows 10 TP環境なんだけど自作のHyper-Vのboxを使いたいならWindows 8.1で作ってくること。 もしくはHyper-Vを諦めて、VirtualBoxとかにする。

VMCX, VMRSファイルの直接編集はサポートしてないとあるが読み出しはできるのだろうか。 Issue投げるのが良さそう。