-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
init.rb
195 lines (173 loc) · 6.68 KB
/
init.rb
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
# 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