1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
# The standard init-based service type. Many other service types are
# customizations of this module.
Puppet::Type.type(:service).provide :init, :parent => :base do
desc "Standard `init`-style service management."
def self.defpath
case Puppet.runtime[:facter].value(:operatingsystem)
when "FreeBSD", "DragonFly"
["/etc/rc.d", "/usr/local/etc/rc.d"]
when "HP-UX"
"/sbin/init.d"
when "Archlinux"
"/etc/rc.d"
when "AIX"
"/etc/rc.d/init.d"
else
"/etc/init.d"
end
end
# Debian and Ubuntu should use the Debian provider.
# RedHat systems should use the RedHat provider.
confine :true => begin
os = Puppet.runtime[:facter].value(:operatingsystem).downcase
family = Puppet.runtime[:facter].value(:osfamily).downcase
!(os == 'debian' || os == 'ubuntu' || family == 'redhat')
end
# We can't confine this here, because the init path can be overridden.
#confine :exists => defpath
# some init scripts are not safe to execute, e.g. we do not want
# to suddenly run /etc/init.d/reboot.sh status and reboot our system. The
# exclude list could be platform agnostic but I assume an invalid init script
# on system A will never be a valid init script on system B
def self.excludes
excludes = []
# these exclude list was found with grep -L '\/sbin\/runscript' /etc/init.d/* on gentoo
excludes += %w{functions.sh reboot.sh shutdown.sh}
# this exclude list is all from /sbin/service (5.x), but I did not exclude kudzu
excludes += %w{functions halt killall single linuxconf reboot boot}
# 'wait-for-state' and 'portmap-wait' are excluded from instances here
# because they take parameters that have unclear meaning. It looks like
# 'wait-for-state' is a generic waiter mainly used internally for other
# upstart services as a 'sleep until something happens'
# (http://lists.debian.org/debian-devel/2012/02/msg01139.html), while
# 'portmap-wait' is a specific instance of a waiter. There is an open
# launchpad bug
# (https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/962047) that may
# eventually explain how to use the wait-for-state service or perhaps why
# it should remain excluded. When that bug is addressed this should be
# reexamined.
excludes += %w{wait-for-state portmap-wait}
# these excludes were found with grep -r -L start /etc/init.d
excludes += %w{rcS module-init-tools}
# Prevent puppet failing on unsafe scripts from Yocto Linux
if Puppet.runtime[:facter].value(:osfamily) == "cisco-wrlinux"
excludes += %w{banner.sh bootmisc.sh checkroot.sh devpts.sh dmesg.sh
hostname.sh mountall.sh mountnfs.sh populate-volatile.sh
rmnologin.sh save-rtc.sh sendsigs sysfs.sh umountfs
umountnfs.sh}
end
# Prevent puppet failing to get status of the new service introduced
# by the fix for this (bug https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/982889)
# due to puppet's inability to deal with upstart services with instances.
excludes += %w{plymouth-ready}
# Prevent puppet failing to get status of these services, which need parameters
# passed in (see https://bugs.launchpad.net/ubuntu/+source/puppet/+bug/1276766).
excludes += %w{idmapd-mounting startpar-bridge}
# Prevent puppet failing to get status of these services, additional upstart
# service with instances
excludes += %w{cryptdisks-udev}
excludes += %w{statd-mounting}
excludes += %w{gssd-mounting}
excludes
end
# List all services of this type.
def self.instances
get_services(self.defpath)
end
def self.get_services(defpath, exclude = self.excludes)
defpath = [defpath] unless defpath.is_a? Array
instances = []
defpath.each do |path|
unless Puppet::FileSystem.directory?(path)
Puppet.debug "Service path #{path} does not exist"
next
end
check = [:ensure]
check << :enable if public_method_defined? :enabled?
Dir.entries(path).each do |name|
fullpath = File.join(path, name)
next if name =~ /^\./
next if exclude.include? name
next if Puppet::FileSystem.directory?(fullpath)
next unless Puppet::FileSystem.executable?(fullpath)
next unless is_init?(fullpath)
instances << new(:name => name, :path => path, :hasstatus => true)
end
end
instances
end
# Mark that our init script supports 'status' commands.
def hasstatus=(value)
case value
when true, "true"; @parameters[:hasstatus] = true
when false, "false"; @parameters[:hasstatus] = false
else
raise Puppet::Error, "Invalid 'hasstatus' value #{value.inspect}"
end
end
# Where is our init script?
def initscript
@initscript ||= self.search(@resource[:name])
end
def paths
@paths ||= @resource[:path].find_all do |path|
if Puppet::FileSystem.directory?(path)
true
else
if Puppet::FileSystem.exist?(path)
self.debug "Search path #{path} is not a directory"
else
self.debug "Search path #{path} does not exist"
end
false
end
end
end
def search(name)
paths.each do |path|
fqname = File.join(path,name)
if Puppet::FileSystem.exist? fqname
return fqname
else
self.debug("Could not find #{name} in #{path}")
end
end
paths.each do |path|
fqname_sh = File.join(path,"#{name}.sh")
if Puppet::FileSystem.exist? fqname_sh
return fqname_sh
else
self.debug("Could not find #{name}.sh in #{path}")
end
end
raise Puppet::Error, "Could not find init script for '#{name}'"
end
# The start command is just the init script with 'start'.
def startcmd
[initscript, :start]
end
# The stop command is just the init script with 'stop'.
def stopcmd
[initscript, :stop]
end
def restartcmd
(@resource[:hasrestart] == :true) && [initscript, :restart]
end
def service_execute(type, command, fof = true, squelch = false, combine = true)
if type == :start && Puppet.runtime[:facter].value(:osfamily) == "Solaris"
command = ["/usr/bin/ctrun -l child", command].flatten.join(" ")
end
super(type, command, fof, squelch, combine)
end
# If it was specified that the init script has a 'status' command, then
# we just return that; otherwise, we return false, which causes it to
# fallback to other mechanisms.
def statuscmd
(@resource[:hasstatus] == :true) && [initscript, :status]
end
private
def self.is_init?(script = initscript)
file = Puppet::FileSystem.pathname(script)
!Puppet::FileSystem.symlink?(file) || Puppet::FileSystem.readlink(file) != "/lib/init/upstart-job"
end
end
|