]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2/Cluster.pm
correctly quote shell arguments inside vzdump cron file
[pve-manager.git] / PVE / API2 / Cluster.pm
CommitLineData
aff192e6
DM
1package PVE::API2::Cluster;
2
3use strict;
4use warnings;
5
6use PVE::SafeSyslog;
7use PVE::Tools qw(extract_param);
7cdf443c 8use PVE::Cluster qw(cfs_register_file cfs_lock_file cfs_read_file cfs_write_file);
aff192e6 9use PVE::Storage;
ac27b58d 10use PVE::API2::Backup;
aff192e6 11use JSON;
aff192e6
DM
12use PVE::RESTHandler;
13use PVE::RPCEnvironment;
14
15use base qw(PVE::RESTHandler);
16
ac27b58d
DM
17__PACKAGE__->register_method ({
18 subclass => "PVE::API2::Backup",
19 path => 'backup',
20});
21
aff192e6
DM
22my $dc_schema = PVE::Cluster::get_datacenter_schema();
23my $dc_properties = {
24 delete => {
25 type => 'string', format => 'pve-configid-list',
26 description => "A list of settings you want to delete.",
27 optional => 1,
28 }
29};
30foreach my $opt (keys %{$dc_schema->{properties}}) {
31 $dc_properties->{$opt} = $dc_schema->{properties}->{$opt};
32}
33
34__PACKAGE__->register_method ({
35 name => 'index',
36 path => '',
37 method => 'GET',
38 description => "Cluster index.",
39 permissions => { user => 'all' },
40 parameters => {
41 additionalProperties => 0,
42 properties => {},
43 },
44 returns => {
45 type => 'array',
46 items => {
47 type => "object",
48 properties => {},
49 },
50 links => [ { rel => 'child', href => "{name}" } ],
51 },
52 code => sub {
53 my ($param) = @_;
54
55 my $result = [
56 { name => 'log' },
57 { name => 'options' },
58 { name => 'resources' },
59 { name => 'tasks' },
ac27b58d 60 { name => 'backup' },
aff192e6
DM
61 ];
62
63 return $result;
64 }});
65
66__PACKAGE__->register_method({
67 name => 'log',
68 path => 'log',
69 method => 'GET',
70 description => "Read cluster log",
71 permissions => { user => 'all' },
72 parameters => {
73 additionalProperties => 0,
74 properties => {
75 max => {
76 type => 'integer',
77 description => "Maximum number of entries.",
78 optional => 1,
79 minimum => 1,
80 }
81 },
82 },
83 returns => {
84 type => 'array',
85 items => {
86 type => "object",
87 properties => {},
88 },
89 },
90 code => sub {
91 my ($param) = @_;
92
93 my $rpcenv = PVE::RPCEnvironment::get();
94
95 my $max = $param->{max} || 0;
96 my $user = $rpcenv->get_user();
97
98 my $admin = $rpcenv->check($user, "/", [ 'Sys.Syslog' ]);
99
100 my $loguser = $admin ? '' : $user;
101
102 my $res = decode_json(PVE::Cluster::get_cluster_log($loguser, $max));
103
104 return $res->{data};
105 }});
106
107__PACKAGE__->register_method({
108 name => 'resources',
109 path => 'resources',
110 method => 'GET',
111 description => "Resources index (cluster wide).",
112 permissions => { user => 'all' },
113 parameters => {
114 additionalProperties => 0,
115 properties => {},
116 },
117 returns => {
118 type => 'array',
119 items => {
120 type => "object",
121 properties => {
122 },
123 },
124 },
125 code => sub {
126 my ($param) = @_;
127
128 my $rpcenv = PVE::RPCEnvironment::get();
129 my $user = $rpcenv->get_user();
130
131 my $res = [];
132
bc7bff8e
DM
133 my $nodelist = PVE::Cluster::get_nodelist();
134 my $members = PVE::Cluster::get_members();
aff192e6
DM
135
136 my $rrd = PVE::Cluster::rrd_dump();
137
138 my $vmlist = PVE::Cluster::get_vmlist() || {};
139 my $idlist = $vmlist->{ids} || {};
140
141
142 # we try to generate 'numbers' by using "$X + 0"
143 foreach my $vmid (keys %$idlist) {
144 my $data = $idlist->{$vmid};
145
146 next if !$rpcenv->check($user, "/vms/$vmid", [ 'VM.Audit' ]);
147
148 my $entry = {
149 id => "$data->{type}/$vmid",
150 vmid => $vmid + 0,
151 node => $data->{node},
152 type => $data->{type},
153 };
154
155 if (my $d = $rrd->{"pve2-vm/$vmid"}) {
156
4380b8d9 157 $entry->{uptime} = ($d->[0] || 0) + 0;
aff192e6
DM
158 $entry->{name} = $d->[1];
159
4380b8d9
DM
160 $entry->{maxcpu} = ($d->[3] || 0) + 0;
161 $entry->{cpu} = ($d->[4] || 0) + 0;
162 $entry->{maxmem} = ($d->[5] || 0) + 0;
163 $entry->{mem} = ($d->[6] || 0) + 0;
164 $entry->{maxdisk} = ($d->[7] || 0) + 0;
165 $entry->{disk} = ($d->[8] || 0) + 0;
aff192e6
DM
166 }
167
168 push @$res, $entry;
169 }
170
bc7bff8e 171 foreach my $node (@$nodelist) {
aff192e6
DM
172 my $entry = {
173 id => "node/$node",
174 node => $node,
175 type => "node",
176 };
177 if (my $d = $rrd->{"pve2-node/$node"}) {
178
8835373d
DM
179 if (!$members || # no cluster
180 ($members->{$node} && $members->{$node}->{online})) {
bc7bff8e
DM
181 $entry->{uptime} = ($d->[0] || 0) + 0;
182 $entry->{cpu} = ($d->[4] || 0) + 0;
183 $entry->{mem} = ($d->[7] || 0) + 0;
184 $entry->{disk} = ($d->[11] || 0) + 0;
185 }
186
4380b8d9 187 $entry->{maxcpu} = ($d->[3] || 0) + 0;
4380b8d9 188 $entry->{maxmem} = ($d->[6] || 0) + 0;
4380b8d9 189 $entry->{maxdisk} = ($d->[10] || 0) + 0;
aff192e6
DM
190 }
191
bc7bff8e 192
aff192e6
DM
193 push @$res, $entry;
194 }
195
196 my $cfg = PVE::Storage::config();
197 my @sids = PVE::Storage::storage_ids ($cfg);
198
199 foreach my $storeid (@sids) {
200 my $scfg = PVE::Storage::storage_config($cfg, $storeid);
201 next if !$rpcenv->check($user, "/storage/$storeid", [ 'Datastore.Audit' ]);
202 # we create a entry for each node
bc7bff8e 203 foreach my $node (@$nodelist) {
aff192e6
DM
204 next if !PVE::Storage::storage_check_enabled($cfg, $storeid, $node, 1);
205 my $entry = {
206 id => "storage/$node/$storeid",
207 storage => $storeid,
208 node => $node,
209 type => 'storage',
210 };
211
212 if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) {
4380b8d9
DM
213 $entry->{maxdisk} = ($d->[1] || 0) + 0;
214 $entry->{disk} = ($d->[2] || 0) + 0;
aff192e6
DM
215 }
216
217 push @$res, $entry;
218
219 }
220 }
221
222 return $res;
223 }});
224
225__PACKAGE__->register_method({
226 name => 'tasks',
227 path => 'tasks',
228 method => 'GET',
229 description => "List recent tasks (cluster wide).",
230 permissions => { user => 'all' },
231 parameters => {
232 additionalProperties => 0,
233 properties => {},
234 },
235 returns => {
236 type => 'array',
237 items => {
238 type => "object",
239 properties => {
240 upid => { type => 'string' },
241 },
242 },
243 },
244 code => sub {
245 my ($param) = @_;
246
247 my $rpcenv = PVE::RPCEnvironment::get();
248 my $user = $rpcenv->get_user();
249
250 my $tlist = PVE::Cluster::get_tasklist();
251
252 my $res = [];
253
254 return $res if !$tlist;
255
256 my $all = $rpcenv->check($user, "/", [ 'Sys.Audit' ]);
257
258 foreach my $task (@$tlist) {
259 push @$res, $task if $all || ($task->{user} eq $user);
260 }
261
262 return $res;
263 }});
264
265__PACKAGE__->register_method({
266 name => 'get_options',
267 path => 'options',
268 method => 'GET',
269 description => "Get datacenter options.",
270 permissions => {
271 path => '/',
272 privs => [ 'Sys.Audit' ],
273 },
274 parameters => {
275 additionalProperties => 0,
276 properties => {},
277 },
278 returns => {
279 type => "object",
280 properties => {},
281 },
282 code => sub {
283 my ($param) = @_;
284 return PVE::Cluster::cfs_read_file('datacenter.cfg');
285 }});
286
287__PACKAGE__->register_method({
288 name => 'set_options',
289 path => 'options',
290 method => 'PUT',
291 description => "Set datacenter options.",
292 permissions => {
293 path => '/',
294 privs => [ 'Sys.Modify' ],
295 },
296 protected => 1,
297 parameters => {
298 additionalProperties => 0,
299 properties => $dc_properties,
300 },
301 returns => { type => "null" },
302 code => sub {
303 my ($param) = @_;
304
305 my $filename = 'datacenter.cfg';
306
307 my $delete = extract_param($param, 'delete');
308
309 my $code = sub {
310
311 my $conf = cfs_read_file($filename);
312
313 foreach my $opt (keys %$param) {
314 $conf->{$opt} = $param->{$opt};
315 }
316
317 foreach my $opt (PVE::Tools::split_list($delete)) {
318 delete $conf->{$opt};
319 };
320
321 cfs_write_file($filename, $conf);
322 };
323
324 cfs_lock_file($filename, undef, $code);
325 die $@ if $@;
326
327 return undef;
328 }});
329
3301;