providers/docker: wait for running state, error if not

This commit is contained in:
Mitchell Hashimoto 2014-04-17 16:20:49 -07:00
parent 09cc823065
commit c0f5095783
6 changed files with 113 additions and 2 deletions

View File

@ -34,8 +34,8 @@ module VagrantPlugins
b2.use SyncedFolderCleanup b2.use SyncedFolderCleanup
b2.use SyncedFolders b2.use SyncedFolders
b2.use PrepareNFSSettings b2.use PrepareNFSSettings
# This will actually create and start, but that's fine
b2.use Create b2.use Create
b2.use WaitForRunning
b2.use action_boot b2.use action_boot
else else
b2.use PrepareNFSValidIds b2.use PrepareNFSValidIds
@ -205,6 +205,7 @@ module VagrantPlugins
Vagrant::Action::Builder.new.tap do |b| Vagrant::Action::Builder.new.tap do |b|
# TODO: b.use SetHostname # TODO: b.use SetHostname
b.use Start b.use Start
b.use WaitForRunning
b.use Call, HasSSH do |env, b2| b.use Call, HasSSH do |env, b2|
if env[:result] if env[:result]
@ -230,6 +231,7 @@ module VagrantPlugins
autoload :PrepareNFSValidIds, action_root.join("prepare_nfs_valid_ids") autoload :PrepareNFSValidIds, action_root.join("prepare_nfs_valid_ids")
autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings") autoload :PrepareNFSSettings, action_root.join("prepare_nfs_settings")
autoload :Start, action_root.join("start") autoload :Start, action_root.join("start")
autoload :WaitForRunning, action_root.join("wait_for_running")
end end
end end
end end

View File

@ -0,0 +1,66 @@
require "thread"
require "log4r"
module VagrantPlugins
module DockerProvider
module Action
class WaitForRunning
def initialize(app, env)
@app = app
@logger = Log4r::Logger.new("vagrant::docker::waitforrunning")
end
def call(env)
machine = env[:machine]
wait = true
if !machine.provider_config.remains_running
wait = false
elsif machine.provider.state.id == :running
wait = false
end
# If we're not waiting, just return
return @app.call(env) if !wait
machine.ui.output(I18n.t("docker_provider.waiting_for_running"))
# First, make sure it leaves the stopped state if its supposed to.
after = sleeper(5)
while machine.provider.state.id == :stopped
if after[:done]
raise Errors::StateStopped
end
sleep 0.2
end
# Then, wait for it to become running
after = sleeper(30)
while true
state = machine.provider.state
break if state.id == :running
@logger.info("Waiting for container to run. State: #{state.id}")
if after[:done]
raise Errors::StateNotRunning
end
sleep 0.2
end
@app.call(env)
end
protected
def sleeper(duration)
Thread.new(duration) do |d|
sleep(d)
Thread.current[:done] = true
end
end
end
end
end
end

View File

@ -14,6 +14,12 @@ module VagrantPlugins
# provisioning, etc. # provisioning, etc.
attr_accessor :has_ssh attr_accessor :has_ssh
# True if the docker container is meant to stay in the "running"
# state (is a long running process). By default this is true.
#
# @return [Boolean]
attr_accessor :remains_running
# The name of the machine in the Vagrantfile set with # The name of the machine in the Vagrantfile set with
# "vagrant_vagrantfile" that will be the docker host. Defaults # "vagrant_vagrantfile" that will be the docker host. Defaults
# to "default" # to "default"
@ -43,6 +49,7 @@ module VagrantPlugins
@image = UNSET_VALUE @image = UNSET_VALUE
@ports = [] @ports = []
@privileged = UNSET_VALUE @privileged = UNSET_VALUE
@remains_running = UNSET_VALUE
@volumes = [] @volumes = []
@vagrant_machine = UNSET_VALUE @vagrant_machine = UNSET_VALUE
@vagrant_vagrantfile = UNSET_VALUE @vagrant_vagrantfile = UNSET_VALUE
@ -54,6 +61,7 @@ module VagrantPlugins
@has_ssh = false if @has_ssh == UNSET_VALUE @has_ssh = false if @has_ssh == UNSET_VALUE
@image = nil if @image == UNSET_VALUE @image = nil if @image == UNSET_VALUE
@privileged = false if @privileged == UNSET_VALUE @privileged = false if @privileged == UNSET_VALUE
@remains_running = true if @remains_running == UNSET_VALUE
@vagrant_machine = nil if @vagrant_machine == UNSET_VALUE @vagrant_machine = nil if @vagrant_machine == UNSET_VALUE
@vagrant_vagrantfile = nil if @vagrant_vagrantfile == UNSET_VALUE @vagrant_vagrantfile = nil if @vagrant_vagrantfile == UNSET_VALUE
end end

View File

@ -58,7 +58,7 @@ module VagrantPlugins
end end
def start(cid) def start(cid)
unless running?(cid) if !running?(cid)
execute('docker', 'start', cid) execute('docker', 'start', cid)
# This resets the cached information we have around, allowing `vagrant reload`s # This resets the cached information we have around, allowing `vagrant reload`s
# to work properly # to work properly

View File

@ -21,6 +21,14 @@ module VagrantPlugins
error_key(:docker_provider_nfs_without_privileged) error_key(:docker_provider_nfs_without_privileged)
end end
class StateNotRunning < DockerError
error_key(:state_not_running)
end
class StateStopped < DockerError
error_key(:state_stopped)
end
class SyncedFolderNonDocker < DockerError class SyncedFolderNonDocker < DockerError
error_key(:synced_folder_non_docker) error_key(:synced_folder_non_docker)
end end

View File

@ -32,6 +32,8 @@ en:
ssh_through_host_vm: |- ssh_through_host_vm: |-
SSH will be proxied through the Docker virtual machine since we're SSH will be proxied through the Docker virtual machine since we're
not running Docker natively. This is just a notice, and not an error. not running Docker natively. This is just a notice, and not an error.
waiting_for_running: |-
Waiting for container to enter "running" state...
messages: messages:
destroying: |- destroying: |-
@ -99,6 +101,31 @@ en:
Stderr: %{stderr} Stderr: %{stderr}
Stdout: %{stdout} Stdout: %{stdout}
state_not_running: |-
The container never entered the "running" state, or entered it
briefly but reverted back to another state. Please verify that
the configuration of the container is correct.
If you meant for this container to not remain running, please
set the Docker provider configuration "remains_running" to "false":
config.vm.provider "docker" do |d|
d.remains_running = false
end
state_stopped: |-
The container started either never left the "stopped" state or
very quickly reverted to the "stopped" state. This is usually
because the container didn't execute a command that kept it running,
and usually indicates a misconfiguration.
If you meant for this container to not remain running, please
set the Docker provider configuration "remains_running" to "false":
config.vm.provider "docker" do |d|
d.remains_running = false
end
synced_folder_non_docker: |- synced_folder_non_docker: |-
The "docker" synced folder type can't be used because the provider The "docker" synced folder type can't be used because the provider
in use is not Docker. This synced folder type only works with the in use is not Docker. This synced folder type only works with the