Skip to content

Instantly share code, notes, and snippets.

@kpumuk
Last active August 29, 2015 14:20
Show Gist options
  • Save kpumuk/c88a80a6dc520e4eed0e to your computer and use it in GitHub Desktop.
Save kpumuk/c88a80a6dc520e4eed0e to your computer and use it in GitHub Desktop.
Default Chef service provider for Centos 6 is totally fucked up. Fixing the damage with this
# Usage:
#
# service svc_name do
# provider Chef::Provider::Service::ScribdRedhat if node[:platform_family] == 'rhel' && node[:platform_version].to_i < 7
# supports status: true, restart: true, stop: true
# action :enable
# end
#
# or enable globally with
#
# Chef::Platform.set(platform: :redhat, version: '< 7', resource: :service, provider: Chef::Provider::Service::ScribdRedhat)
#
class Chef::Provider::Service::ScribdRedhat < Chef::Provider::Service::Redhat
def define_resource_requirements
super
requirements.assert(:start, :enable, :reload, :restart) do |a|
a.assertion { @service_starting }
a.failure_message Chef::Exceptions::Service, "#{@new_resource}: service does not start automatically, probably by mistake!"
a.whyrun "Assuming service would be automatically started."
end
end
def load_current_resource
super
@service_starting = true
if ::File.exists?("/sbin/chkconfig") && !@service_missing && service_fucked_up?(@current_resource.enabled)
unfuck_the_fucking_service!(@current_resource.enabled)
end
@current_resource
end
def unfuck_the_fucking_service!(enabled)
svc = @current_resource.service_name
Chef::Log.warn("Service #{svc} is fucked up: unfucking")
if enabled
Chef::Log.warn("Service #{svc} is fucked up: expected to be enabled, enabling")
enable_service
else
Chef::Log.warn("Service #{svc} is fucked up: expected to be disabled, disabling")
disable_service
end
end
def service_fucked_up?(enabled)
svc = @current_resource.service_name
::File.read("/etc/rc.d/init.d/#{svc}").each_line do |l|
if l =~ /#\s*chkconfig:\s+([-\d]+)\s+(\d+)\s+(\d+)/
runlevels, start_priority, kill_priority = $1, $2.to_i, $3.to_i
srunlevels = if runlevels == '-'
@service_starting = false if l !~ /DO NOT START AUTOMATICALLY/
[]
elsif !enabled
[]
else
runlevels.scan(/./).map(&:to_i).sort
end
krunlevels = enabled ? (0..6).to_a - srunlevels : []
start_runlevels = get_service_runlevels('S')
# Do we have start script on all requested run levels?
if start_runlevels.keys.sort != srunlevels
Chef::Log.warn("Service #{svc} is fucked up: expected to start on levels #{srunlevels.inspect}, actually starts on #{start_runlevels.keys.sort.inspect}")
return true
end
start_runlevels.each do |level, priorities|
# More than one start script for the service?
if priorities.size > 1
Chef::Log.warn("Service #{svc} is fucked up: there multiple start scripts on level #{level} with priorities #{priorities.inspect}")
return true
end
# Start priority does not match?
if priorities[0] != start_priority
Chef::Log.warn("Service #{svc} is fucked up: on level #{level} start priority is #{priorities[0].inspect}, but #{start_prioriry.inspect} expected")
return true
end
end
kill_runlevels = get_service_runlevels('K')
# Do we have kill script on all requested run levels?
if kill_runlevels.keys.sort != krunlevels
Chef::Log.warn("Service #{svc} is fucked up: expected to stop on levels #{krunlevels.inspect}, actually stops on #{kill_runlevels.keys.sort.inspect}")
return true
end
kill_runlevels.each do |level, priorities|
# More than one kill script for the service?
if priorities.size > 1
Chef::Log.warn("Service #{svc} is fucked up: there multiple stop scripts on level #{level} with priorities #{priorities.inspect}")
return true
end
# Stop priority does not match?
if priorities[0] != kill_priority
Chef::Log.warn("Service #{svc} is fucked up: on level #{level} stop priority is #{priorities[0].inspect}, but #{kill_prioriry.inspect} expected")
return true
end
end
return false
end
end
# chkconfig line is missing, probably ok...
return false
end
def get_service_runlevels(prefix)
::Dir["/etc/rc.d/rc?.d/#{prefix}*#{@current_resource.service_name}"].each_with_object({}) do |path, hash|
_, level, priority = path.match(%r{/rc\.d/rc(\d)\.d/#{prefix}(\d+)}).to_a
hash[level.to_i] ||= []
hash[level.to_i] << priority.to_i
end
end
def enable_service()
shell_out! "/sbin/chkconfig #{@new_resource.service_name} reset"
end
def disable_service()
shell_out! "/sbin/chkconfig --del #{@new_resource.service_name}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment