最初に結論を書いとくと、一部しか実現できていない。
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_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
に変えたらエラーは出なくなった。ただし正常に設定変更できたわけではないので、まだ何か問題があるっぽい。
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上で報告してもらえると助かります。