しばたテックブログ

気分で書いている技術ブログです。

日本語Windows OSに対してvagrant upするとIPアドレスの設定に失敗するのでパッチを書きました


【2015/12/22 追記】
特に公式なアナウンスはありませんが*1Vagrant 1.8.0でこの問題は解決した様です。
私の環境ではVagrant 1.8.0にしてこの問題が解決しています。


ちょっとタイトルが変なのですがvagrant up時に発生するエラーとそれに対応するためのパッチを書きました。
一応拙い英語で頑張ってIssueをあげたのでPull Requestを送るかもしれません。

起きてること

日本語Windows OSのVagrant Boxを作り、Private Networkの設定(Static/DHCPどちらでも)をしてvagrant upをすると、以下の様なエラーを出してIPアドレスの設定に失敗することがあります。

==> default: Configuring and enabling network interfaces...
The following WinRM command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

netsh interface ip set address "?????? 2" static 192.168.1.100 255.255.255.0
if ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }

Stdout from the command:

Stderr from the command:

Vagrantfile例

# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
  config.vm.box = "Win81-64"
  config.vm.guest = :windows
  config.vm.communicator = "winrm"
  config.vm.network :forwarded_port, guest: 3389, host: 13389
  config.vm.network :forwarded_port, guest: 5985, host: 15985, id: "winrm", auto_correct: true
  # ↓この設定に失敗する
  config.vm.network "private_network", ip: "192.168.1.100"

  config.vm.provider "virtualbox" do |vb|
    vb.gui = true
    vb.memory = "4098"
  end
end

原因

RubyWinRMライブラリが日本語を正しく扱えておらず、NIC名が文字化けしてしまいnetsh interfaceコマンドに失敗してしまいます。

現在のVagrant(1.7.2)で使用されているWinRMのバージョンは1.1.3で、このバージョンのWinRMはWindows 2008R2までならある程度日本語を扱えるのですが以降のOSに対しては完全に日本語が化けてしまう様です。
ちなみにWinRMの最新バージョンは1.3.0で、このバージョンで内部のコードページを変更すれば日本語を正しく扱える様です。*2

パッチ

Gistに上げてます。適用方法はGistに載せています。

VagrantでWindowsゲストのNIC名が日本語の場合でもIPアドレスの設定を行える様にするパ ...

このパッチではnetsh interfaceコマンドでIPアドレスを設定している部分を、Win32_NetworkAdapterConfigurationクラスのWin32_NetworkAdapterConfiguration.EnableStatic/EnableDHCPメソッドに置き換えています。

# netsh interfaceコマンドだとIPアドレスの設定にNIC名(#{net_connection_id})が必要
"netsh interface ip set address \"#{net_connection_id}\" static #{ip} #{netmask}"# Win32_NetworkAdapterConfigurationクラスを使うとIPアドレスの設定にNIC名が不要。
# メソッドの戻り値を呼び出し元に返すためにReturnValueプロパティの値を返している。
"&{exit (Get-WMiObject Win32_NetworkAdapterConfiguration -Filter \"Index=#{nic_index}\").EnableStatic(@(\"#{ip}\"), @(\"#{netmask}\")).ReturnValue}"

Win32_NetworkAdapterConfiguration.EnableStatic/EnableDHCPメソッドではIPアドレスの設定にNIC名称が不要なため文字化けによるエラーを回避することができます。

*1:以前に上げたIssueはエンコーディングの問題が多すぎると却下されてしまったので...

*2:ただ、現在はコードページを外部から変える方法がないので、こちらについても別途Issueを上げようと思います