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
|
Puppet::Type.type(:service).provide :base do
desc "The simplest form of service support. You have to specify
enough about your service for this to work; the minimum you can specify
is a binary for starting the process, and this same binary will be searched
for in the process table to stop the service. It is preferable to
specify start, stop, and status commands, akin to how you would do
so using ``init``."
commands :kill => "kill"
# Get the process ID for a running process. Requires the 'pattern'
# parameter.
def getpid
unless @resource[:pattern]
@resource.fail "Either a stop command or a pattern must be specified"
end
ps = Facter["ps"].value
unless ps and ps != ""
@resource.fail(
"You must upgrade Facter to a version that includes 'ps'"
)
end
regex = Regexp.new(@resource[:pattern])
self.debug "Executing '#{ps}'"
IO.popen(ps) { |table|
table.each { |line|
if regex.match(line)
ary = line.sub(/^\s+/, '').split(/\s+/)
return ary[1]
end
}
}
return nil
end
# How to restart the process.
def restart
if @resource[:restart] or self.respond_to?(:restartcmd)
ucommand(:restart)
else
self.stop
self.start
end
end
# Check if the process is running. Prefer the 'status' parameter,
# then 'statuscmd' method, then look in the process table. We give
# the object the option to not return a status command, which might
# happen if, for instance, it has an init script (and thus responds to
# 'statuscmd') but does not have 'hasstatus' enabled.
def status
if @resource[:status] or (
self.respond_to?(:statuscmd) and self.statuscmd
)
# Don't fail when the exit status is not 0.
output = ucommand(:status, false)
self.debug "%s status returned %s" %
[self.name, output.inspect]
if $? == 0
return :running
else
return :stopped
end
elsif pid = self.getpid
self.debug "PID is %s" % pid
return :running
else
return :stopped
end
end
# Run the 'start' parameter command, or the specified 'startcmd'.
def start
ucommand(:start)
end
# The command used to start. Generated if the 'binary' argument
# is passed.
def startcmd
if @resource[:binary]
return @resource[:binary]
else
raise Puppet::Error,
"Services must specify a start command or a binary"
end
end
# Stop the service. If a 'stop' parameter is specified, it
# takes precedence; otherwise checks if the object responds to
# a 'stopcmd' method, and if so runs that; otherwise, looks
# for the process in the process table.
# This method will generally not be overridden by submodules.
def stop
if @resource[:stop] or self.respond_to?(:stopcmd)
ucommand(:stop)
else
pid = getpid
unless pid
self.info "%s is not running" % self.name
return false
end
begin
output = kill pid
rescue Puppet::ExecutionFailure => detail
@resource.fail "Could not kill %s, PID %s: %s" %
[self.name, pid, output]
end
return true
end
end
# A simple wrapper so execution failures are a bit more informative.
def texecute(type, command, fof = true)
begin
# #565: Services generally produce no output, so squelch them.
execute(command, :failonfail => fof, :squelch => true)
rescue Puppet::ExecutionFailure => detail
@resource.fail "Could not %s %s: %s" % [type, @resource.ref, detail]
end
return nil
end
# Use either a specified command or the default for our provider.
def ucommand(type, fof = true)
if c = @resource[type]
cmd = [c]
else
cmd = self.send("%scmd" % type)
end
return texecute(type, cmd, fof)
end
end
# $Id$
|