Last active
August 29, 2015 14:20
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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