]> git.proxmox.com Git - pve-manager.git/blame - lib/PVE/API2/Services.pm
imported from svn 'pve-manager/pve2'
[pve-manager.git] / lib / PVE / API2 / Services.pm
CommitLineData
aff192e6
DM
1package PVE::API2::Services;
2
3use strict;
4use warnings;
5
6use PVE::Tools;
7use PVE::SafeSyslog;
8use PVE::Cluster;
9use PVE::INotify;
10use PVE::Exception qw(raise_param_exc);
11use PVE::RESTHandler;
12use PVE::RPCEnvironment;
13use PVE::JSONSchema qw(get_standard_option);
14use PVE::AccessControl;
15use IO::File;
16
17use base qw(PVE::RESTHandler);
18
19my $service_list = {
20 apache => { name => 'WWW', desc => 'Web/API server' },
21 postfix => { name => 'SMTP', desc => 'Simple Mail Tranfer Protocol' },
22 ntpd => { name => 'NTP', desc => 'Network time protocol' },
23 sshd => { name => 'SSH', desc => 'Secure shell daemon' },
24 syslog => { name => 'Syslog', desc => 'Syslog daemon' },
25 cron => { name => 'CRON', desc => 'Daemon to execute scheduled commands' },
26 pvedaemon => { name => 'NodeManager', desc => 'PVE node manager daemon' },
27 corosync => { name => 'Corosync', desc => 'Corosync cluster daemon' },
28 pvecluster => { name => 'PVECluster', desc => 'Proxmox VE cluster file system' },
29};
30
31my $service_cmd = sub {
32 my ($service, $cmd) = @_;
33
34 my $initd_cmd;
35
36 die "unknown service command '$cmd'\n"
37 if $cmd !~ m/^(start|stop|restart|reload)$/;
38
39 $cmd = $1; # untaint
40
41 if ($service eq 'postfix') {
42 $initd_cmd = '/etc/init.d/postfix';
43 } elsif ($service eq 'pvecluster') {
44 if ($cmd eq 'restart') {
45 $initd_cmd = '/etc/init.d/pve-cluster';
46 } else {
47 die "invalid service cmd 'pve-cluster $cmd': ERROR";
48 }
49 } elsif ($service eq 'pvedaemon') {
50 if ($cmd eq 'restart') {
51 $initd_cmd = '/etc/init.d/pvedaemon';
52 } else {
53 die "invalid service cmd '$service $cmd': ERROR";
54 }
55 } elsif ($service eq 'apache') {
56 if ($cmd eq 'restart') {
57 $initd_cmd = '/usr/sbin/apache2ctl';
58 $cmd = 'graceful';
59 } else {
60 die "invalid service cmd '$service $cmd': ERROR";
61 }
62 } elsif ($service eq 'ntpd') {
63 # debian start/stop scripts does not work for us
64 if ($cmd eq 'stop') {
65 system ('/etc/init.d/ntp stop');
66 #system ('/usr/bin/killall /usr/sbin/ntpd');
67 } elsif ($cmd eq 'start') {
68 system ('/etc/init.d/ntp start');
69 system ('/sbin/hwclock --systohc');
70 } elsif ($cmd eq 'restart') {
71 system ('/etc/init.d/ntp restart');
72 system ('/sbin/hwclock --systohc');
73 # restart cron/syslog to get right schedules and log time/dates
74 system ('/etc/init.d/rsyslog restart');
75 system ('/etc/init.d/cron restart');
76 }
77 return 0;
78 } elsif ($service eq 'syslog') {
79 $initd_cmd = '/etc/init.d/rsyslog';
80 } elsif ($service eq 'cron') {
81 $initd_cmd = '/etc/init.d/cron';
82 } elsif ($service eq 'corosync') {
83 $initd_cmd = '/etc/init.d/cman';
84 } elsif ($service eq 'sshd') {
85 $initd_cmd = '/etc/init.d/ssh';
86 } else {
87 die "unknown service '$service': ERROR";
88 }
89
90 PVE::Tools::run_command ([$initd_cmd, $cmd]);
91};
92
93my $service_state = sub {
94 my ($service) = @_;
95
96 my $pid_file;
97
98 if ($service eq 'postfix') {
99 $pid_file = '/var/spool/postfix/pid/master.pid';
100 } elsif ($service eq 'apache') {
101 $pid_file = '/var/run/apache2.pid';
102 } elsif ($service eq 'pvedaemon') {
103 $pid_file = '/var/run/pvedaemon.pid';
104 } elsif ($service eq 'pvecluster') {
105 $pid_file = '/var/run/pve-cluster.pid';
106 } elsif ($service eq 'ntpd') {
107 $pid_file = '/var/run/ntpd.pid';
108 } elsif ($service eq 'sshd') {
109 $pid_file = '/var/run/sshd.pid';
110 } elsif ($service eq 'cron') {
111 $pid_file = '/var/run/crond.pid';
112 } elsif ($service eq 'corosync') {
113 $pid_file = '/var/run/corosync.pid';
114 } elsif ($service eq 'syslog') {
115 $pid_file = '/var/run/rsyslogd.pid';
116 } else {
117 die "unknown service '$service': ERROR";
118 }
119
120 my $pid;
121 if (my $fh = IO::File->new ($pid_file, "r")) {
122 my $line = <$fh>;
123 chomp $line;
124
125 if ($line && ($line =~ m/^\s*(\d+)\s*$/)) {
126 $pid = $1;
127 }
128 }
129
130 return 'running' if ($pid && kill (0, $pid));
131
132 return 'stopped';
133};
134
135__PACKAGE__->register_method ({
136 name => 'index',
137 path => '',
138 method => 'GET',
139 permissions => {
140 path => '/nodes/{node}',
141 privs => [ 'Sys.Audit' ],
142 },
143 description => "Service list.",
144 proxyto => 'node',
145 protected => 1,
146 parameters => {
147 additionalProperties => 0,
148 properties => {
149 node => get_standard_option('pve-node'),
150 },
151 },
152 returns => {
153 type => 'array',
154 items => {
155 type => "object",
156 properties => {},
157 },
158 links => [ { rel => 'child', href => "{service}" } ],
159 },
160 code => sub {
161 my ($param) = @_;
162
163 my $res = [];
164
165 foreach my $id (keys %{$service_list}) {
166 push @$res, {
167 service => $id,
168 name => $service_list->{$id}->{name},
169 desc => $service_list->{$id}->{desc},
170 state => &$service_state($id),
171 };
172 }
173
174 return $res;
175 }});
176
177__PACKAGE__->register_method ({
178 name => 'state',
179 path => '{service}',
180 method => 'GET',
181 permissions => {
182 path => '/nodes/{node}',
183 privs => [ 'Sys.Audit' ],
184 },
185 description => "Read service properties",
186 proxyto => 'node',
187 protected => 1,
188 parameters => {
189 additionalProperties => 0,
190 properties => {
191 node => get_standard_option('pve-node'),
192 service => {
193 description => "Service ID",
194 type => 'string',
195 enum => [ keys %{$service_list} ],
196 },
197 },
198 },
199 returns => {
200 type => "object",
201 properties => {},
202 },
203 code => sub {
204 my ($param) = @_;
205
206 my $si = $service_list->{$param->{service}};
207 return {
208 service => $param->{service},
209 name => $si->{name},
210 desc => $si->{desc},
211 state => &$service_state($param->{service}),
212 };
213 }});
214
215__PACKAGE__->register_method ({
216 name => 'cmd',
217 path => '{service}',
218 method => 'PUT',
219 description => "Execute service commands.",
220 proxyto => 'node',
221 protected => 1,
222 parameters => {
223 additionalProperties => 0,
224 properties => {
225 node => get_standard_option('pve-node'),
226 service => {
227 description => "Service ID",
228 type => 'string',
229 enum => [ keys %{$service_list} ],
230 },
231 command => {
232 description => "The command to execute. The only valid command for service 'apache' and 'pvedaemon' is 'restart', because both services are required by this API.",
233 type => 'string',
234 enum => [qw(start stop restart reload)],
235 },
236 },
237 },
238 returns => { type => 'null'},
239 code => sub {
240 my ($param) = @_;
241
242 my $si = $service_list->{$param->{service}};
243 &$service_cmd($param->{service}, $param->{command});
244
245 return undef;
246 }});