LoginSignup
11
9

More than 5 years have passed since last update.

Vagrant で起動したゲスト Windows のネットワーク設定

Last updated at Posted at 2014-04-04

最初に結論を書いとくと、一部しか実現できていない。

Vagrant で Windows もゲストOSに - Qiitaで書いた通り、Windowsでも好きなように作ったり壊したりできるようになりました。そこからいろいろ試してみたところ欲が出てきて、製品のデモ環境も Vagrant で作れるんじゃ?と考えたのが運のつき。

やろうとした環境は以下の通り。ゲストOSにいろいろ仕込んで、外部からアクセスできる環境を構築しつつ、ホストは汚さない環境を構築したかった。

外部PC(192.168.2.100)

ブリッジアダプター

ゲストOS(192.168.2.1)
ゲストOS(192.168.56.100)

ホストオンリーアダプター

ホストOS(192.168.56.1)

vagrant up してからゲストOSでネットワーク設定を変更すればいいんだけど、面倒なのでそれも自動化しようとしてみた。

まずは Private Networks - Networking - Vagrant Documentation を参考に private_network を設定する。これがホストオンリーアダプターに相当する。今回は DHCP でなく static で指定したいので IP アドレスを設定。次に Public Networks - Networking - Vagrant Documentation を参考に public_network を設定する。これがブリッジアダプターに相当する。 あとは IP アドレス、と思ったらこっちは DHCP しか設定できないらしい・・・ → ドキュメントに記載がないけど、今は設定できるらしい。

仕方ないので以下のように設定した。

Vagrantfile
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.network "private_network", ip: "192.168.2.1"
  config.vm.network "public_network", ip: "192.168.56.100"
end

これで vagrant up すると、ネットワークアダプターを3つ持った VM が起動する(1つはポートフォワーディングした NAT )。なんだけどアダプターの IP アドレスは設定されていない。

これはなぜかと言うと、文字コードのせいで WinRM 経由の netsh が失敗しているため。試しにホストオンリーアダプターの名前を「ローカル エリア接続 2」から「local network」のようにASCII文字列オンリーに変更すれば正しく IP アドレスが 192.168.2.1 に設定される。
もちろんホストOS側を 192.168.2.1 以外にしておく前提。

ちなみにエラーはこんな感じ。

Shell: powershell
Command: netsh interface ip set address "ローカル エリア接続 2" static 192.168.2.1 255.255.255.0
Message: U+30ED from UTF-8 to ASCII-8BIT>
ERROR vagrant: An error occurred executing a remote WinRM command.

2014/04/06 追記
Vagrant-Windows が依存してる WinRb/WinRM が ASCII に決め打ちでエンコードしてるのが原因っぽい。 script = script.encode('ASCII-8BIT')Windows-31J に変えたらエラーは出なくなった。ただし正常に設定変更できたわけではないので、まだ何か問題があるっぽい。

winrm/winrm_service.rb
    def run_powershell_script(script_file, &block)
      # if an IO object is passed read it..otherwise assume the contents of the file were passed
      script = script_file.kind_of?(IO) ? script_file.read : script_file

      script = script.chars.to_a.join("\x00").chomp
      script << "\x00" unless script[-1].eql? "\x00"
      if(defined?(script.encode))
        script = script.encode('ASCII-8BIT')
        script = Base64.strict_encode64(script)
      else
        script = Base64.encode64(script).chomp
      end

      shell_id = open_shell
      command_id = run_command(shell_id, "powershell -encodedCommand #{script}")
      command_output = get_command_output(shell_id, command_id, &block)
      cleanup_command(shell_id, command_id)
      close_shell(shell_id)
      command_output
    end
    alias :powershell :run_powershell_script

2014/04/09 追記
powershell に -encodedCommand オプションを指定しているので、 Windows-31J を指定しても意味はなさそう。エラーを避けつつ Base64 で送信するには以下のようにすればいいと思うんだけど、まだ解決できていない。

-script = script.encode('ASCII-8BIT')
+script = script.force_encoding('ASCII-8BIT').encode('ASCII-8BIT')

2014/06/26 追記
この件に関しては Configurating network adapter failed when NON-ASCII adapter name used. · Issue #182 · WinRb/vagrant-windows として issue 登録済み。
また、Vagrant-Windowsが依存しているWinRMに対して Fix PowerShell encoding from ASCII-8BIT to UTF-16LE for NON-ASCII string... by toruuetani · Pull Request #70 · WinRb/WinRM としてPR済み

PRしている変更をWinRMに対して適用すれば、正しくネットワーク設定できることを確認済みです。ただ、十分テストできているとは言えないので、試してみたらGitHub上で報告してもらえると助かります。

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9