環境依存かもしれないけど Windows8.1 上で いつの間にか Vagrant できなくなってて辛いめにあったので忘備録。 あまり綺麗でないかもしれないけど使えるようになりました。

header

【2014-11-23 追記】 とある経緯で Comodo Internet Security を使わなくなったところ、 この現象がピタリと止まりました。うーむ。。。

問題の状態

screenshot

vagrant upすると起動の過程でunknownステータスを掴んで途中でコケる。 起動はしたりしなかったり、多くは共有フォルダまで処理されないので、 無理やり使おうにもとにかく不便。てかunknownってなんですかね・・・(´・ω・`)

原因

とりまVirtualBoxのProviderをあさって見ることに。 Vagrantのインストール先のディレクトリから下記の場所に、 VMの状態を記録してそうなとこがあったのでまずそこからみてみます。

対象: C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-1.6.3\plugins\providers\virtualbox\provider.rb

# Return the state of VirtualBox virtual machine by actually
# querying VBoxManage.
#
# @return [Symbol]
def state
# Determine the ID of the state here.
state_id = nil
state_id = :not_created if !@driver.uuid
state_id = @driver.read_state if !state_id
state_id = :unknown if !state_id

# Translate into short/long descriptions
short = state_id.to_s.gsub("_", " ")
long  = I18n.t("vagrant.commands.status.#{state_id}")

# If we're not created, then specify the special ID flag
if state_id == :not_created
  state_id = Vagrant::MachineState::NOT_CREATED_ID
end

# Return the state
Vagrant::MachineState.new(state_id, short, long)
end

・・・どうやらunknown自体はプロバイダから状態を取得できなくて どうしようもない場合に帰ってくる様子。

実際、stateの状態を追ってみたら稀にnilが帰ってきて状態を取得できていないようでした。

解決方法

直接の原因がVagrantかVirtualBoxなのかはさておき、 とにかく使えないのがあれなので状態取得でunknownを食らった時に待機するように修正してみました。 幸いなことにデフォルトで待機処理が入るようになっていたので意外と楽でした。

対象: C:\HashiCorp\Vagrant\embedded\gems\gems\vagrant-1.6.3\lib\vagrant\action\builtin\wait_for_communicator.rb

module Vagrant
  module Action
    module Builtin
      # This waits for the communicator to be ready for a set amount of
      # time.
      class WaitForCommunicator
        def call(env)

# ...

        # Otherwise, periodically verify the VM isn't in a bad state.
        while true
          state = env[:machine].state.id

          # Used to report invalid states
          Thread.current[:last_known_state] = state

          # Check if we have the proper state so we can break out
          # if @states && !@states.include?(state)
          if @states && !@states.include?(state) && (state != :unknown) #<= unknownを受け付けないように修正
            Thread.current[:result] = false
            break
          end

          # Sleep a bit so we don't hit 100% CPU constantly.
          sleep 1
        end

# ...

修正箇所はwhileをbreakする条件に&& (state != :unknown)を追記するだけ。

これで状態を取得できない時に1秒待機してから再度状態を取得するように出来ました。 自分の環境だとちゃんとVagrantできるようになったことを確認できました。


関連リンク