]>
Commit | Line | Data |
---|---|---|
163fb58f DM |
1 | package PMG::API2::Services; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | ||
6 | use PVE::Tools; | |
7 | use PVE::SafeSyslog; | |
8 | use PVE::INotify; | |
9 | use PVE::Exception qw(raise_param_exc); | |
10 | use PVE::RESTHandler; | |
9d82c6bc | 11 | use PMG::RESTEnvironment; |
163fb58f DM |
12 | use PVE::JSONSchema qw(get_standard_option); |
13 | ||
621a0f58 DM |
14 | use PMG::Utils; |
15 | ||
163fb58f DM |
16 | use base qw(PVE::RESTHandler); |
17 | ||
18 | my $service_name_list = [ | |
d77e8aeb DM |
19 | 'clamav-daemon', |
20 | 'clamav-freshclam', | |
163fb58f DM |
21 | 'pmgproxy', |
22 | 'pmgdaemon', | |
db2ee3df | 23 | 'pmgpolicy', |
8ed62155 | 24 | 'pmg-smtp-filter', |
9fc351a8 | 25 | 'ssh', |
0b21df28 | 26 | 'rsyslog', |
163fb58f DM |
27 | 'postfix', |
28 | 'systemd-timesyncd', | |
a34e0908 DM |
29 | 'pmg-hourly', |
30 | 'pmg-daily', | |
163fb58f DM |
31 | ]; |
32 | ||
33 | my $get_full_service_state = sub { | |
34 | my ($service) = @_; | |
35 | ||
36 | my $res; | |
37 | ||
38 | my $parser = sub { | |
39 | my $line = shift; | |
40 | if ($line =~ m/^([^=\s]+)=(.*)$/) { | |
41 | $res->{$1} = $2; | |
42 | } | |
43 | }; | |
44 | ||
aab6fe36 | 45 | $service = 'postfix@-' if $service eq 'postfix'; |
163fb58f DM |
46 | PVE::Tools::run_command(['systemctl', 'show', $service], outfunc => $parser); |
47 | ||
48 | return $res; | |
49 | }; | |
50 | ||
51 | my $static_service_list; | |
52 | ||
53 | sub get_service_list { | |
54 | ||
55 | return $static_service_list if $static_service_list; | |
56 | ||
57 | my $list = {}; | |
58 | foreach my $name (@$service_name_list) { | |
59 | my $ss; | |
60 | eval { $ss = &$get_full_service_state($name); }; | |
61 | warn $@ if $@; | |
62 | next if !$ss; | |
63 | next if !defined($ss->{Description}); | |
64 | $list->{$name} = { name => $name, desc => $ss->{Description} }; | |
65 | } | |
66 | ||
67 | $static_service_list = $list; | |
68 | ||
69 | return $static_service_list; | |
70 | } | |
71 | ||
72 | ||
73 | my $service_prop_desc = { | |
74 | description => "Service ID", | |
75 | type => 'string', | |
76 | enum => $service_name_list, | |
77 | }; | |
78 | ||
163fb58f DM |
79 | my $service_state = sub { |
80 | my ($service) = @_; | |
81 | ||
82 | my $ss; | |
83 | eval { $ss = &$get_full_service_state($service); }; | |
84 | if (my $err = $@) { | |
85 | return 'unknown'; | |
86 | } | |
87 | ||
1bd0a5fb | 88 | my $state = $ss->{SubState} // 'unknown'; |
163fb58f | 89 | |
1bd0a5fb DM |
90 | $state = $ss->{Result} |
91 | if $state eq 'dead' && $ss->{Type} && $ss->{Type} eq 'oneshot' && | |
92 | $ss->{Result}; | |
93 | ||
94 | return $state; | |
163fb58f DM |
95 | }; |
96 | ||
97 | __PACKAGE__->register_method ({ | |
98 | name => 'index', | |
99 | path => '', | |
100 | method => 'GET', | |
101 | description => "Service list.", | |
102 | proxyto => 'node', | |
103 | protected => 1, | |
104 | parameters => { | |
105 | additionalProperties => 0, | |
106 | properties => { | |
107 | node => get_standard_option('pve-node'), | |
108 | }, | |
109 | }, | |
110 | returns => { | |
111 | type => 'array', | |
112 | items => { | |
113 | type => "object", | |
114 | properties => {}, | |
115 | }, | |
116 | links => [ { rel => 'child', href => "{service}" } ], | |
117 | }, | |
118 | code => sub { | |
119 | my ($param) = @_; | |
120 | ||
121 | my $res = []; | |
122 | ||
123 | my $service_list = get_service_list(); | |
124 | ||
125 | foreach my $id (keys %{$service_list}) { | |
126 | push @$res, { | |
127 | service => $id, | |
128 | name => $service_list->{$id}->{name}, | |
129 | desc => $service_list->{$id}->{desc}, | |
1bd0a5fb | 130 | state => $service_state->($id), |
163fb58f DM |
131 | }; |
132 | } | |
133 | ||
134 | return $res; | |
135 | }}); | |
136 | ||
137 | __PACKAGE__->register_method({ | |
138 | name => 'srvcmdidx', | |
139 | path => '{service}', | |
140 | method => 'GET', | |
141 | description => "Directory index", | |
142 | parameters => { | |
143 | additionalProperties => 0, | |
144 | properties => { | |
145 | node => get_standard_option('pve-node'), | |
146 | service => $service_prop_desc, | |
147 | }, | |
148 | }, | |
149 | returns => { | |
150 | type => 'array', | |
151 | items => { | |
152 | type => "object", | |
153 | properties => { | |
154 | subdir => { type => 'string' }, | |
155 | }, | |
156 | }, | |
157 | links => [ { rel => 'child', href => "{subdir}" } ], | |
158 | }, | |
159 | code => sub { | |
160 | my ($param) = @_; | |
161 | ||
162 | my $res = [ | |
163 | { subdir => 'state' }, | |
164 | { subdir => 'start' }, | |
165 | { subdir => 'stop' }, | |
166 | { subdir => 'restart' }, | |
167 | { subdir => 'reload' }, | |
168 | ]; | |
169 | ||
170 | return $res; | |
171 | }}); | |
172 | ||
173 | __PACKAGE__->register_method ({ | |
174 | name => 'service_state', | |
175 | path => '{service}/state', | |
176 | method => 'GET', | |
177 | description => "Read service properties", | |
178 | proxyto => 'node', | |
179 | protected => 1, | |
180 | parameters => { | |
181 | additionalProperties => 0, | |
182 | properties => { | |
183 | node => get_standard_option('pve-node'), | |
184 | service => $service_prop_desc, | |
185 | }, | |
186 | }, | |
187 | returns => { | |
188 | type => "object", | |
189 | properties => {}, | |
190 | }, | |
191 | code => sub { | |
192 | my ($param) = @_; | |
193 | ||
194 | my $service_list = get_service_list(); | |
195 | ||
196 | my $si = $service_list->{$param->{service}}; | |
197 | return { | |
198 | service => $param->{service}, | |
199 | name => $si->{name}, | |
200 | desc => $si->{desc}, | |
201 | state => &$service_state($param->{service}), | |
202 | }; | |
203 | }}); | |
204 | ||
205 | __PACKAGE__->register_method ({ | |
206 | name => 'service_start', | |
207 | path => '{service}/start', | |
208 | method => 'POST', | |
209 | description => "Start service.", | |
210 | proxyto => 'node', | |
211 | protected => 1, | |
212 | parameters => { | |
213 | additionalProperties => 0, | |
214 | properties => { | |
215 | node => get_standard_option('pve-node'), | |
216 | service => $service_prop_desc, | |
217 | }, | |
218 | }, | |
219 | returns => { | |
220 | type => 'string', | |
221 | }, | |
222 | code => sub { | |
223 | my ($param) = @_; | |
224 | ||
9d82c6bc | 225 | my $restenv = PMG::RESTEnvironment::get(); |
163fb58f DM |
226 | |
227 | my $user = $restenv->get_user(); | |
228 | ||
229 | my $realcmd = sub { | |
230 | my $upid = shift; | |
231 | ||
232 | syslog('info', "starting service $param->{service}: $upid\n"); | |
233 | ||
621a0f58 | 234 | PMG::Utils::service_cmd($param->{service}, 'start'); |
163fb58f DM |
235 | |
236 | }; | |
237 | ||
238 | return $restenv->fork_worker('srvstart', $param->{service}, $user, $realcmd); | |
239 | }}); | |
240 | ||
241 | __PACKAGE__->register_method ({ | |
242 | name => 'service_stop', | |
243 | path => '{service}/stop', | |
244 | method => 'POST', | |
245 | description => "Stop service.", | |
246 | proxyto => 'node', | |
247 | protected => 1, | |
248 | parameters => { | |
249 | additionalProperties => 0, | |
250 | properties => { | |
251 | node => get_standard_option('pve-node'), | |
252 | service => $service_prop_desc, | |
253 | }, | |
254 | }, | |
255 | returns => { | |
256 | type => 'string', | |
257 | }, | |
258 | code => sub { | |
259 | my ($param) = @_; | |
260 | ||
9d82c6bc | 261 | my $restenv = PMG::RESTEnvironment::get(); |
163fb58f DM |
262 | |
263 | my $user = $restenv->get_user(); | |
264 | ||
265 | my $realcmd = sub { | |
266 | my $upid = shift; | |
267 | ||
268 | syslog('info', "stoping service $param->{service}: $upid\n"); | |
269 | ||
621a0f58 | 270 | PMG::Utils::service_cmd($param->{service}, 'stop'); |
163fb58f DM |
271 | |
272 | }; | |
273 | ||
274 | return $restenv->fork_worker('srvstop', $param->{service}, $user, $realcmd); | |
275 | }}); | |
276 | ||
277 | __PACKAGE__->register_method ({ | |
278 | name => 'service_restart', | |
279 | path => '{service}/restart', | |
280 | method => 'POST', | |
281 | description => "Restart service.", | |
282 | proxyto => 'node', | |
283 | protected => 1, | |
284 | parameters => { | |
285 | additionalProperties => 0, | |
286 | properties => { | |
287 | node => get_standard_option('pve-node'), | |
288 | service => $service_prop_desc, | |
289 | }, | |
290 | }, | |
291 | returns => { | |
292 | type => 'string', | |
293 | }, | |
294 | code => sub { | |
295 | my ($param) = @_; | |
296 | ||
9d82c6bc | 297 | my $restenv = PMG::RESTEnvironment::get(); |
163fb58f DM |
298 | |
299 | my $user = $restenv->get_user(); | |
300 | ||
301 | my $realcmd = sub { | |
302 | my $upid = shift; | |
303 | ||
304 | syslog('info', "re-starting service $param->{service}: $upid\n"); | |
305 | ||
621a0f58 | 306 | PMG::Utils::service_cmd($param->{service}, 'restart'); |
163fb58f DM |
307 | |
308 | }; | |
309 | ||
310 | return $restenv->fork_worker('srvrestart', $param->{service}, $user, $realcmd); | |
311 | }}); | |
312 | ||
313 | __PACKAGE__->register_method ({ | |
314 | name => 'service_reload', | |
315 | path => '{service}/reload', | |
316 | method => 'POST', | |
317 | description => "Reload service.", | |
318 | proxyto => 'node', | |
319 | protected => 1, | |
320 | parameters => { | |
321 | additionalProperties => 0, | |
322 | properties => { | |
323 | node => get_standard_option('pve-node'), | |
324 | service => $service_prop_desc, | |
325 | }, | |
326 | }, | |
327 | returns => { | |
328 | type => 'string', | |
329 | }, | |
330 | code => sub { | |
331 | my ($param) = @_; | |
332 | ||
9d82c6bc | 333 | my $restenv = PMG::RESTEnvironment::get(); |
163fb58f DM |
334 | |
335 | my $user = $restenv->get_user(); | |
336 | ||
337 | my $realcmd = sub { | |
338 | my $upid = shift; | |
339 | ||
340 | syslog('info', "reloading service $param->{service}: $upid\n"); | |
341 | ||
621a0f58 | 342 | PMG::Utils::service_cmd($param->{service}, 'reload'); |
163fb58f DM |
343 | |
344 | }; | |
345 | ||
346 | return $restenv->fork_worker('srvreload', $param->{service}, $user, $realcmd); | |
347 | }}); |