On Aug 24, 2008, at 1:41 PM, Brice Figureau wrote:
>
>
> This path adds a service provider to manage daemontools[1]
> services directly from puppet.
>
> The daemons directories should be placed in /var/lib/service
> (overridable with the service path parameter).
> When the service is enabled, the daemon directory is symlinked
> into the service directory which defaults to /service
> (or /etc/service on debian). The daemon is then started by svscan.
> Services are disabled by removing this symlink.
> Start and stop are almost directly mapped to enable/disable.
> This provider supports restart and status directly
Cool, I'm glad to see someone supporting this.
As James mentioned, we can't accept this into the main repo without
tests, but we can work with you to get those done, too.
>
> Comments are welcome.
>
> Signed-off-by: Brice Figureau <[EMAIL PROTECTED]>
> ---
> lib/puppet/provider/service/daemontools.rb | 147 +++++++++++++++++++
> +++++++++
> 1 files changed, 147 insertions(+), 0 deletions(-)
> create mode 100644 lib/puppet/provider/service/daemontools.rb
>
> diff --git a/lib/puppet/provider/service/daemontools.rb b/lib/puppet/
> provider/service/daemontools.rb
> new file mode 100644
> index 0000000..194bbbe
> --- /dev/null
> +++ b/lib/puppet/provider/service/daemontools.rb
> @@ -0,0 +1,147 @@
> +# Daemontools service management
> +#
> +# author Brice Figureau <[EMAIL PROTECTED]>
> +Puppet::Type.type(:service).provide :daemontools, :parent => :base do
> + desc "Daemontools service management. The daemons directories
> should be
> + placed in ``/var/lib/service`` (overridable with the service
> path). When enabled
> + the daemon directories are symlinked to the service directory
> (and the daemon started
> + by svscan). Services are disabled by unlinking this symlink.
> + Start and stop are almost directly mapped to enable/disable.
> + This provider supports restart and status directly"
> +
> + commands :svc => "/usr/bin/svc"
> + commands :svstat => "/usr/bin/svstat"
> +
> + class << self
> + attr_accessor :defpath
> + end
> +
> + @defpath = "/var/lib/service"
> + case Facter["operatingsystem"].value
> + when "Debian":
> + @@enabledpath = "/etc/service"
> + else
> + @@enabledpath = "/service"
> + end
Why the split between defpath and enabledpath? Am I just missing
something about them?
>
> + # returns all providers for all existing services in @defpath
> + # ie enabled or not
> + def self.instances
> + path = self.defpath
> + unless FileTest.directory?(path)
> + Puppet.notice "Service path %s does not exist" % path
> + next
> + end
> +
> + check = [:ensure]
> +
> + if public_method_defined? :enabled?
> + check << :enable
> + end
This 'check' variable isn't actually used anywhere that I can see...
>
> + Dir.entries(path).reject { |e|
> + fullpath = File.join(path, e)
> + e =~ /^\./ or ! FileTest.directory?(fullpath)
> + }.collect do |name|
> + new(:name => name, :path => path)
> + end
> + end
> +
> + # Mark that our services supports 'status' commands
> unconditionally
> + def hasstatus=(value)
> + @parameters[:hasstatus] = true
> + end
Doesn't daemontools always have status? In that case, you should
probably have a different default for this value.
>
> + # Where is our appdir
> + def appdir
> + if defined? @appdir
> + return @appdir
> + else
> + @appdir = self.search(@resource[:name], @resource[:path])
> + end
> + end
> +
> + # Where is our daemon if it was enabled
> + # which doesn't mean there is always one
> + def servicedir
> + if defined? @servicedir
> + return @servicedir
> + else
> + @servicedir = File.join( @@enabledpath,
> @resource[:name] )
> + end
> + end
I'd prefer to see an accessor like the defpath above used for
enabledpath. In fact, I'd even prefer to see the 'resource' accessor
used rather than @resource.
Both are stylistic, but they're what I'd do, at least partially
because they make testing much easier.
>
> + def restartcmd
> + [ command(:svc), "-t", self.servicedir]
> + end
> +
> + # find a service by its name an the path in which it is
> + def search(name, path)
> + path = [path] unless path.is_a?(Array)
> + path.each { |path|
> + fqname = File.join(path,name)
> + begin
> + stat = File.stat(fqname)
> + rescue
> + # should probably rescue specific errors...
> + self.debug("Could not find %s in %s" % [name,path])
> + next
> + end
> +
> + # if we've gotten this far, we found a valid script
> + return fqname
> + }
> + raise Puppet::Error, "Could not find service link in
> service directory for '%s'" % name
> + end
> +
> + # The start command does nothing, service are automatically
> started
> + # when enabled by svscan. But, forces an enable if necessary
> + def start
> + # to start make sure the sevice is enabled
> + self.enable unless self.enabled?
> + end
You shouldn't need the 'unless' here, afaik; Puppet's transaction
should only call this if it's convinced it's not currently started.
>
> + def status
> + begin
> + output = svstat self.servicedir
> + rescue Puppet::ExecutionFailure
> + warning "Could not get status on service %s" % self.name
> + return :stopped
You're probably going to want to throw an exception here, rather than
just warning, since it's unlikely that Puppet will be able to do
anything like start the service if it can't even check the status.
>
> + end
> + return :running if output =~ /\bup\b/
> + return :stopped
> + end
> +
> + # unfortunately it is not possible
> + # to stop without disabling the service
> + def stop
> + self.disable
> + end
> +
> + # disable by stopping the service
> + # and removing the symlink so that svscan
> + # doesn't restart our service behind our back
> + def disable
> + # should stop the service
> + # stop log if any
> + log = File.join(self.servicedir, "log")
> + texecute("stop log", [ command(:svc) , '-dx', log] ) if
> FileTest.directory?(log)
Does this "stop log" work? I think that texecute expects an array and
does a direct system call, which would mean looking for a binary named
'stop log'.
Also, if 'stop' is an executable used by the provider, it should be
listed as a command at the top. Your standard 'stop' method will
still work here, I'm pretty sure, although I don't think I've had that
kind of collision before. If it's an optional command, use
'optional_commands :stop => foo'.
>
> + # stop resource
> + texecute("stop", [command(:svc), '-dx', self.servicedir] )
> +
> + # unlink the symlinks
> + appdir = self.servicedir
> + File.unlink(appdir) if FileTest.symlink?(appdir)
> + end
> +
> + def enabled?
> + FileTest.symlink?(self.servicedir)
> + end
> +
> + def enable
> + srcdir = self.appdir
> + enableddir = self.servicedir
> + File.symlink(srcdir, enableddir) if ! FileTest.symlink?
> (enableddir)
> + end
> +end
--
Happiness is not achieved by the conscious pursuit of happiness; it is
generally the by-product of other activities. -- Aldous Huxley
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://madstop.com
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---