diff options
| author | Nigel Kersten <nigelk@google.com> | 2008-11-25 07:37:23 -0800 |
|---|---|---|
| committer | James Turnbull <james@lovedthanlost.net> | 2008-11-26 13:01:44 +1100 |
| commit | 86ce934270992d192a1163d211761a505d5b2812 (patch) | |
| tree | a13d2b625960c7e15e74c6b4f394c0d39fc85c2b /lib/puppet/provider/service/launchd.rb | |
| parent | 97a817706f7993044b69f148fe2ba74bbcb5d4a3 (diff) | |
| download | puppet-86ce934270992d192a1163d211761a505d5b2812.tar.gz puppet-86ce934270992d192a1163d211761a505d5b2812.tar.xz puppet-86ce934270992d192a1163d211761a505d5b2812.zip | |
launchd service provider
Diffstat (limited to 'lib/puppet/provider/service/launchd.rb')
| -rw-r--r-- | lib/puppet/provider/service/launchd.rb | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/lib/puppet/provider/service/launchd.rb b/lib/puppet/provider/service/launchd.rb new file mode 100644 index 000000000..e51451cac --- /dev/null +++ b/lib/puppet/provider/service/launchd.rb @@ -0,0 +1,188 @@ +require 'facter/util/plist' + +Puppet::Type.type(:service).provide :launchd, :parent => :base do + desc "launchd service management framework. + + This provider manages launchd jobs, the default service framework for + Mac OS X, that has also been open sourced by Apple for possible use on + other platforms. + + See: + * http://developer.apple.com/macosx/launchd.html + * http://launchd.macosforge.org/ + + This provider reads plists out of the following directories: + * /System/Library/LaunchDaemons + * /System/Library/LaunchAgents + * /Library/LaunchDaemons + * /Library/LaunchAgents + + and builds up a list of services based upon each plists \"Label\" entry. + + This provider supports: + * ensure => running/stopped, + * enable => true/false + * status + * restart + + Here is how the Puppet states correspond to launchd states: + * stopped => job unloaded + * started => job loaded + * enabled => 'Disable' removed from job plist file + * disabled => 'Disable' added to job plist file + + Note that this allows you to do something launchctl can't do, which is to + be in a state of \"stopped/enabled\ or \"running/disabled\". + " + + commands :launchctl => "/bin/launchctl" + + defaultfor :operatingsystem => :darwin + confine :operatingsystem => :darwin + + has_feature :enableable + + Launchd_Paths = ["/Library/LaunchAgents", + "/Library/LaunchDaemons", + "/System/Library/LaunchAgents", + "/System/Library/LaunchDaemons",] + + + # returns a label => path map for either all jobs, or just a single + # job if the label is specified + def self.jobsearch(label=nil) + label_to_path_map = {} + Launchd_Paths.each do |path| + if FileTest.exists?(path) + Dir.entries(path).each do |f| + next if f =~ /^\..*$/ + next if FileTest.directory?(f) + fullpath = File.join(path, f) + job = Plist::parse_xml(fullpath) + if job and job.has_key?("Label") + if job["Label"] == label + return { label => fullpath } + else + label_to_path_map[job["Label"]] = fullpath + end + end + end + end + end + + # if we didn't find the job above and we should have, error. + if label + raise Puppet::Error.new("Unable to find launchd plist for job: #{label}") + end + # if returning all jobs + label_to_path_map + end + + + def self.instances + jobs = self.jobsearch + jobs.keys.collect do |job| + new(:name => job, :provider => :launchd, :path => jobs[job]) + end + end + + + # finds the path for a given label and returns the path and parsed plist + # as an array of [path, plist]. Note plist is really a Hash here. + def self.plist_from_label(label) + job = self.jobsearch(label) + job_path = job[label] + job_plist = Plist::parse_xml(job_path) + if not job_plist + raise Puppet::Error.new("Unable to parse launchd plist at path: #{job_path}") + end + [job_path, job_plist] + end + + + def status + # launchctl list <jobname> exits zero if the job is loaded + # and non-zero if it isn't. Simple way to check... + cmds = [] + cmds << :launchctl << "list" << @resource[:name] + begin + execute(cmds) + return :running + rescue Puppet::ExecutionFailure + return :stopped + end + end + + + # start the service. To get to a state of running/enabled, we need to + # conditionally enable at load, then disable by modifying the plist file + # directly. + def start + job = self.class.jobsearch(@resource[:name]) + job_path = job[@resource[:name]] + did_enable_job = false + cmds = [] + cmds << :launchctl << "load" + if self.enabled? == :false # launchctl won't load disabled jobs + cmds << "-w" + did_enable_job = true + end + cmds << job_path + begin + execute(cmds) + rescue Puppet::ExecutionFailure + raise Puppet::Error.new("Unable to start service: %s at path: %s" % [@resource[:name], job_path]) + end + # As load -w clears the Disabled flag, we need to add it in after + if did_enable_job and @resource[:enable] == :false + self.disable + end + end + + + def stop + job = self.class.jobsearch(@resource[:name]) + job_path = job[@resource[:name]] + cmds = [] + cmds << :launchctl << "unload" << job_path + begin + execute(cmds) + rescue Puppet::ExecutionFailure + raise Puppet::Error.new("Unable to stop service: %s at path: %s" % [@resource[:name], job_path]) + end + end + + + # launchd jobs are enabled by default. They are only disabled if the key + # "Disabled" is set to true, but it can also be set to false to enable it. + def enabled? + job_path, job_plist = self.class.plist_from_label(@resource[:name]) + if job_plist.has_key?("Disabled") + if job_plist["Disabled"] # inverse of disabled is enabled + return :false + end + end + return :true + end + + + # enable and disable are a bit hacky. We write out the plist with the appropriate value + # rather than dealing with launchctl as it is unable to change the Disabled flag + # without actually loading/unloading the job. + def enable + job_path, job_plist = self.class.plist_from_label(@resource[:name]) + if not self.enabled? + job_plist.delete("Disabled") + Plist::Emit.save_plist(job_plist, job_path) + end + end + + + def disable + job_path, job_plist = self.class.plist_from_label(@resource[:name]) + job_plist["Disabled"] = true + Plist::Emit.save_plist(job_plist, job_path) + end + + +end |
