From 85d3f25d51a23fba892a8b852f8dc3d446e37cf2 Mon Sep 17 00:00:00 2001 From: Joe Crobak Date: Mon, 3 Feb 2014 21:45:48 +0000 Subject: [PATCH] Update all LWRPs to check that docker is alive. Before issuing any commands that talk to the local docker daemon, make sure it is running (since its service starts in the background). --- attributes/default.rb | 1 + libraries/helpers.rb | 49 ++++++++++++++++++++++++++++++++++++++++++ providers/container.rb | 1 + providers/image.rb | 1 + providers/registry.rb | 1 + 5 files changed, 53 insertions(+) diff --git a/attributes/default.rb b/attributes/default.rb index 94acdb2b7e..8e84963af4 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -14,6 +14,7 @@ default['docker']['http_proxy'] = nil default['docker']['image_cmd_timeout'] = 300 default['docker']['registry_cmd_timeout'] = 60 +default['docker']['docker_daemon_timeout'] = 10 default['docker']['init_type'] = value_for_platform( %w{ centos debian oracle redhat } => { diff --git a/libraries/helpers.rb b/libraries/helpers.rb index 069620879f..7a65341e3c 100644 --- a/libraries/helpers.rb +++ b/libraries/helpers.rb @@ -1,7 +1,25 @@ +require 'chef/mixin/shell_out' +include Chef::Mixin::ShellOut + # Helpers module module Helpers # Helpers::Docker module module Docker + class DockerNotReady < StandardError + def initialize(endpoint, timeout) + super <<-EOH +The Docker daemon did not become ready within #{timeout} seconds. +This most likely means that Docker failed to start. +Docker can fail to start if: + + - a configuration file is invalid + - permissions are incorrect for the root directory of the docker runtime. + +If this problem persists, check your service log files. +EOH + end + end + def cli_args(spec) cli_line = '' spec.each_pair do |arg, value| @@ -18,5 +36,36 @@ def cli_args(spec) end cli_line end + + def timeout + node['docker']['docker_daemon_timeout'] + end + + # This is based upon wait_until_ready! from the opscode jenkins cookbook. + # + # Since the docker service returns immediately and the actual docker + # process is started as a daemon, we block the Chef Client run until the + # daemon is actually ready. + # + # This method will effectively "block" the current thread until the docker + # daemon is ready + # + # @raise [DockerNotReady] + # if the Docker master does not respond within (+timeout+) seconds + # + def wait_until_ready! + Timeout.timeout(timeout) do + while true do + result = shell_out('docker info') + if not !Array(result.valid_exit_codes).include?(result.exitstatus) + break + end + Chef::Log.debug("Docker daemon is not running - #{result.stdout}\n#{result.stderr}") + sleep(0.5) + end + end + rescue Timeout::Error + raise DockerNotReady.new(timeout) + end end end diff --git a/providers/container.rb b/providers/container.rb index 1d4c958354..f55065cde8 100644 --- a/providers/container.rb +++ b/providers/container.rb @@ -6,6 +6,7 @@ class CommandTimeout < RuntimeError; end def load_current_resource @current_resource = Chef::Resource::DockerContainer.new(new_resource) + wait_until_ready! dps = docker_cmd('ps -a -notrunc') dps.stdout.each_line do |dps_line| next unless dps_line.include?(new_resource.image) diff --git a/providers/image.rb b/providers/image.rb index d619438d6f..8ee2db77cf 100644 --- a/providers/image.rb +++ b/providers/image.rb @@ -5,6 +5,7 @@ class CommandTimeout < RuntimeError; end def load_current_resource + wait_until_ready! @current_resource = Chef::Resource::DockerImage.new(new_resource) di = docker_cmd('images -a') if di.stdout.include?(new_resource.image_name) diff --git a/providers/registry.rb b/providers/registry.rb index b5d71014f2..0414c90f6a 100644 --- a/providers/registry.rb +++ b/providers/registry.rb @@ -6,6 +6,7 @@ class CommandTimeout < RuntimeError; end def load_current_resource @current_resource = Chef::Resource::DockerRegistry.new(new_resource) + wait_until_ready! # TODO: load current resource? @current_resource end