Feature #1014
Services should support 'reload' in addition to 'restart'
| Status: | Accepted | Start date: | ||
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | - | % Done: | 0% |
|
| Category: | service | |||
| Target version: | 3.X | |||
| Affected Puppet version: | 0.24.7 | Branch: | ||
| Keywords: | ||||
| Votes: | 12 |
Description
currently if a service needs kicking (e.g. a config file changed) you can notify the service, but this leads to a restart. It would be nice if a reload was done if the service was already running (although I suppose there are bound to be some services which require restarts for some files, reloads for others).
A reload would be far faster (shorter service interruption) and potentially more robust.
I’m looking at this since bind stop/start (I hadn’t set “hasrestart”) on Debian etch can fail – it looks like stop command doesn’t wait for bind to exit (I’ll raise a bug with Debian about that)
Related issues
History
Updated by Luke Kanies over 4 years ago
How would you want this to be configured? I’ve been thinking we need to redesign the service parameters anyway, so that we had a single ‘has’ parameter, that could then accept ‘restart’, ‘reload’, ‘status’, and more.
Updated by Adrian Bridgett over 4 years ago
The most complex example I can think of is something like Apache. Normally you can just ask it to reload, however sometimes you need to request a restart instead (if you add/remove modules for example).
I presume “has” can be added to? We are shortly going to turn “hasrestart” on by default (due to that bind issue above, all the init scripts I’ve seen so far have supported restart). So we’d be setting hasrestart on a global level and then possibly overriding it for specific services (either unsetting it or adding “status” to the list of haves).
FWIW on Debian there is a “force-reload” which should be provided by most init.d scripts – this does reload (if the program supports it) or restart (if it doesn’t).
What we currently do is this which isn’t too bad, but hides the fact that we are reloading the apache2 service.
class apache2::apache2 {
service { "apache2":
enable => true,
ensure => true,
hasrestart => true,
}
exec { "reload":
command => "/etc/init.d/apache2 reload",
refreshonly => true,
require => Service[[apache2]],
}
define site ( $ensure = 'present' ) {
...
notify => Exec[[reload]],
}
define mod ( $ensure = 'present') {
...
notify => Service[[apache2]],
}
}
Many thanks
Updated by Luke Kanies over 4 years ago
So some relationships would result in a restart, and some would result in a reload, in this Apache example?
How would you want to differentiate between those two in the language?
Updated by shamot - about 4 years ago
Hello
I am definitely up for this feature as Apache restart instead of reload (suppose the change where reload is sufficient was made) could be very dangerous in certain situations. If restart on production servers is done then in case of apache configuration typo Apache wont IMO start again. Concerning we are running more Apache servers and one config typo resulting to stop them all could be a serious problem.
as far as new configuration design is concerned what about something like:
notify => Service[[apache2""reload]] notify => Service[[apache2""restart]]
It’s just a suggestion, which maybe isn’t even possible due to puppy configuration concept/design.
Thanks
Tomas
Updated by Russ Allbery about 4 years ago
I certainly do agree that the feature is desireable, but as a matter of best practice you should also make the restart action in the Apache init script depend on the successful completion of apache2ctl/apachectl configtest. That will help prevent any restarts, whether from Puppet or by an administrator, from causing nasty surprises.
One way to do this is to modify the init script. Another way in Puppet would be:
restart => "/usr/sbin/apache2ctl configtest && /etc/init.d/apache2 restart"
(using the Debian paths).
Updated by Adrian Bridgett about 4 years ago
Thinking about it, I wonder if supporting generic actions would be possible. There is restart and reload, but there could be other actions too (e.g. test, stop, start). Asterisk for example has several kinds of reloads (sip reload, extension reload). These should be associated with the service I think. Oh for object orientated puppet ;–)
Updated by Redmine Admin almost 4 years ago
- Status changed from 1 to Needs Decision
Updated by anarcat - about 3 years ago
- Affected Puppet version set to 0.24.7
I agree with Luke that making “has” more generic would definitly help here. However, we have yet to resolve the reload vs restart paradigm: if you notify the service, is reload or restart fired?
I would think that reload should be fired if available and that’s it.
Note that this currently breaks Nagios under moderate load here: if Puppet adds a new configuration file to the nagios setup (using files, I haven’t tried the native resources yet) and then goes around restarting nagios, nagios will simly crash because ‘restart’ is unreliable (it properly restarts the server, which sometimes fails because of timeoouts) whereas reload is much more reliable (it just SIGHUP’s the server).
Maybe this should be a fix in the Debian provider to use reload when available…
Updated by Eric Eisenhart about 3 years ago
It’s terrible, but the descriptions earlier in this ticket don’t properly capture the complexity of managing apache. With apache, there’s a third option, “graceful”.
On RHEL, I use:
restart => "/sbin/service httpd graceful",
From the man page: “[graceful] differs from a normal restart in that currently open connections are not aborted.”. In other words, it takes longer, but it eliminates the possibility of user problems (closed connections halfway through downloading something, etc.) This is normally what I prefer for changing the configuration of apache, and is what I would recommend for most cases.
Apache aside, there’s also some init scripts on my RHEL systems that have other kinds of “restart”, such as “force-reload”, “forcerestart”. Yes, in some cases those are equivalent to something else (such as “force-reload” == “restart”), but for others it really does something different (with autofs it adds —force to command-lines which unmounts things). I haven’t had to use any of those, but surely somebody someday will need to…
Updated by James Turnbull almost 3 years ago
- Assignee deleted (
Puppet Community)
Updated by Nigel Kersten over 1 year ago
- Assignee set to Nigel Kersten
Updated by Jordan Sissel over 1 year ago
I think notify doing reload-or-restart oversimplifies things. There are other possibly-confusing issues like when you notify a custom define. If that defines a service and an exec, both will get notified. It’s possible the notify-custom-define issue is worth another ticket.
Some thoughts –
That said, if we want a reusable solution, I think it’s about ‘who’ and ‘how’ – who to notify, and how to notify them. The complexities in some applications (apache) mean a human needs to understand when a restart is required or when a reload is sufficient, which begs for some kind of syntax for describing this in puppet.
It gets more complex because you can notify multiple things from a single change. Notify is a special case in puppet in that it puts data on edges in the graph, right? A notify is just a ‘before’ relationship plus some data with that relationship (not sure how it’s implemented in the code, but that’s how I think of it). What if we expanded that a bit? Are there other things we want to store in the edges?
Alternately, notify can be thought of a as a way for one resource to message another when that first resource changes.
Maybe we can expand on 2.6’s –> and <– syntax? Something like
# Syntax idea 1
File["/etc/apache2/sites-enabled/mysite.conf"] -> Service["apache2"]("reload")
Package["apache2"] -> reload Service["apache2"]("restart")
# the () syntax is optional, having (...) would imply a notify
# Syntax idea 2
File["/etc/apache2/sites-enabled/mysite.conf"] -> reload Service["apache2"]
Package["apache2"] -> restart Service["apache2"]
# The first token after the -> would be the 'how' in our notify
# Defining the service:
service {
"apache2":
ensure => ...,.
reload => "some command", # defaults to the provider's "reload"
restart => "some command", # just like today
hasrestart => ..., # just like today
hasreload => ...,
}
Custom defines get a bit trickier and may require some new syntax. Maybe a new meta resource called ‘notification’ or ‘notify’ ? Classes could use this, too!
define foo() {
notify {
"restart": Exec["some command"];
"something": [Service["apache2"], AnotherResource["..."]];
}
}
class bar {
notify {
"config-updated": Service["apache2"];
}
}
# Now we could do:
MyResource["..."] -> "config-updated" Class["bar"]
MyResource["..."] -> "something" Foo["..."]
Thoughts?
Updated by Nigel Kersten over 1 year ago
- Status changed from Needs Decision to Accepted
- Assignee deleted (
Nigel Kersten)
“if we want a reusable solution, I think it’s about ‘who’ and ‘how’ – who to notify, and how to notify them. ”
Absolutely. I don’t want to keep hacking special cases up when we could solve them all by solving the “how” problem.
Updated by Nigel Kersten 12 months ago
- Target version changed from 4 to 3.X
Just noting #7594 where we’re aiming at more useful notifications.
This ticket will remain targeted at adding “reload” to the Service type.
Updated by James Turnbull 9 months ago
I added some code that doesn’t make this simpler in #3323 but provides the capability to reload and graceful where the init script has those.
Updated by Jonathan Boyett 3 months ago
+1 to the code in #3323.
Updated by Daniel Pittman 3 months ago
Jonathan Boyett wrote:
+1 to the code in #3323.
The same basic commentary applies to this as it does to the graceful equivalent: having more and more boolean values representing what is really a “pick one” option is terrible. This should unify the various “please restart like this” options in a sane way, and until then folks can work around it by explicitly setting the command by hand.