diff options
author | robuye <rulejczyk@gmail.com> | 2019-09-17 11:54:23 +0200 |
---|---|---|
committer | robuye <rulejczyk@gmail.com> | 2019-09-17 14:44:26 +0200 |
commit | ec177edf55504e56de1ba1319f5eca8351614e46 (patch) | |
tree | 0fddc22c69ca0444a1ccf1384fe71f93914871d5 /lib/chef/provider | |
parent | 1c642e292f1356454e0e226c7d33c3bb45dec8fb (diff) | |
download | chef-ec177edf55504e56de1ba1319f5eca8351614e46.tar.gz |
bring back support for legacy update-rc.d syntax
Legacy syntax is required to support start & stop priorities on very old
systems running SysVinit. If an old enough version is detected Chef will
prefer legacy syntax, otherwise it will use modern syntax and the
priorities will be for the most part ignored.
See https://lists.debian.org/debian-devel/2013/05/msg01109.html for
additional context.
To use legacy syntax sysv-rc package must be installed and it's version
must be < 2.88. If the package is not installed at all then update-rc.d
is coming from 'init-system-helpers' package and it's at least
2.88dsf-59.2 so it supports only modern syntax.
Note that start|stop syntax has been dropped in 2.88dsf-42 and older
2.88 versions could work, but the email linked above indicates it didn't
do anything.
Signed-off-by: Rob Ulejczyk <rulejczyk@gmail.com>
Diffstat (limited to 'lib/chef/provider')
-rw-r--r-- | lib/chef/provider/service/debian.rb | 86 |
1 files changed, 73 insertions, 13 deletions
diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb index 6774b214ae..0fea83ab0f 100644 --- a/lib/chef/provider/service/debian.rb +++ b/lib/chef/provider/service/debian.rb @@ -149,43 +149,103 @@ class Chef end def enable_service + # We call the same command regardless if we're enabling or disabling + # Users passing a Hash are responsible for setting their own stop priorities if new_resource.priority.is_a? Hash - # we call the same command regardless of we're enabling or disabling - # users passing a Hash are responsible for setting their own start priorities set_priority - else # No priority or Integer. Either way go with update-rc.d defaults - shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove") - shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} defaults") + return end + + start_priority = new_resource.priority.is_a?(Integer) ? new_resource.priority : 20 + # Stop processes in reverse order of start using '100 - start_priority'. + stop_priority = 100 - start_priority + + shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove") + shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} defaults #{start_priority} #{stop_priority}") end def disable_service if new_resource.priority.is_a? Hash - # we call the same command regardless of we're enabling or disabling - # users passing a Hash are responsible for setting their own stop priorities + # We call the same command regardless if we're enabling or disabling + # Users passing a Hash are responsible for setting their own stop priorities set_priority - else # No priority or Integer. Either way disable in all levels. - shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove") + return + end + + shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove") + + # Use legacy syntax if update-rc.d supports it for backward compatibility. + if use_legacy_update_rc_d? + # If no priority was given assume 20 (update-rc.d default). + start_priority = new_resource.priority.is_a?(Integer) ? new_resource.priority : 20 + # Stop processes in reverse order of start using '100 - start_priority'. + stop_priority = 100 - start_priority + + shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} stop #{stop_priority} 2 3 4 5 .") + else shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} defaults") shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} disable") end end def set_priority + shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove") + + # Use legacy syntax if update-rc.d supports it for backward compatibility. + if use_legacy_update_rc_d? + args = "" + new_resource.priority.each do |level, o| + action = o[0] + priority = o[1] + args += "#{action} #{priority} #{level} . " + end + shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} #{args}") + return + end + + # Use modern syntax, ignoring priorities as update-rc.d does not support it. + # # Reset priorities to default values before applying customizations. This way # the final state will always be consistent, regardless if all runlevels were # provided. - shell_out!("/usr/sbin/update-rc.d -f #{new_resource.service_name} remove") shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} defaults") - - # Note the `_priority` is not used. update-rc.d does not support priorities - # anymore, this feature has been dropped in sysvinit 2.88dsf-42. new_resource.priority.each do |level, (action, _priority)| disable_or_enable = (action == :start ? "enable" : "disable") shell_out!("/usr/sbin/update-rc.d #{new_resource.service_name} #{disable_or_enable} #{level}") end end + + # Ancient Debian releases used run levels and priorities to manage dependencies ordering. + # Old syntax no longer works and new syntax does not support priorities. If Chef detects + # ancient update-rc.d it will prefer legacy syntax so priorities can be set correctly in + # case the host is in fact running SysVinit. + # + # Additional context: https://lists.debian.org/debian-devel/2013/05/msg01109.html + def use_legacy_update_rc_d? + @sysv_rc_version ||= shell_out!("dpkg-query -W --showformat '${Version}' sysv-rc").stdout.strip + + # sysv-rc is not installed therefore we're on modern Debian and legacy syntax does not work + if @sysv_rc_version.empty? + logger.trace("sysv-rc package is not installed. update-rc.d will use modern syntax") + return false + end + + # sysv-rc is installed and update-rc.d is old enough to support legacy syntax and features + if @sysv_rc_version.to_f < 2.88 + logger.trace("sysv-rc #{@sysv_rc_version} detected. update-rc.d will use legacy syntax") + return true + end + + # sysv-rc 2.88dsf-42 drops the legacy syntax + if @sysv_rc_version.to_f == 2.88 && @sysv_rc_version[8..9].to_i < 42 + logger.trace("sysv-rc #{@sysv_rc_version} detected. update-rc.d will use legacy syntax") + return true + end + + # default to modern syntax + false + end end end end |