]>
git.proxmox.com Git - pve-manager.git/blob - PVE/API2/Cluster.pm
0d2d3b3dfd3b1519548ec1970db7f8aae8f91055
1 package PVE
::API2
::Cluster
;
7 use PVE
::Tools
qw(extract_param);
8 use PVE
::Cluster
qw(cfs_register_file cfs_lock_file cfs_read_file cfs_write_file);
11 use PVE
::API2
::VZDump
;
14 use Data
::Dumper
; # fixme: remove
16 use Apache2
::Const
qw(:http);
19 use PVE
::RPCEnvironment
;
21 use base
qw(PVE::RESTHandler);
23 my $dc_schema = PVE
::Cluster
::get_datacenter_schema
();
26 type
=> 'string', format
=> 'pve-configid-list',
27 description
=> "A list of settings you want to delete.",
31 foreach my $opt (keys %{$dc_schema->{properties
}}) {
32 $dc_properties->{$opt} = $dc_schema->{properties
}->{$opt};
35 __PACKAGE__-
>register_method ({
39 description
=> "Cluster index.",
40 permissions
=> { user
=> 'all' },
42 additionalProperties
=> 0,
51 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
58 { name
=> 'options' },
59 { name
=> 'resources' },
67 __PACKAGE__-
>register_method({
71 description
=> "Read cluster log",
72 permissions
=> { user
=> 'all' },
74 additionalProperties
=> 0,
78 description
=> "Maximum number of entries.",
94 my $rpcenv = PVE
::RPCEnvironment
::get
();
96 my $max = $param->{max
} || 0;
97 my $user = $rpcenv->get_user();
99 my $admin = $rpcenv->check($user, "/", [ 'Sys.Syslog' ]);
101 my $loguser = $admin ?
'' : $user;
103 my $res = decode_json
(PVE
::Cluster
::get_cluster_log
($loguser, $max));
108 __PACKAGE__-
>register_method({
112 description
=> "Resources index (cluster wide).",
113 permissions
=> { user
=> 'all' },
115 additionalProperties
=> 0,
129 my $rpcenv = PVE
::RPCEnvironment
::get
();
130 my $user = $rpcenv->get_user();
134 my $nodelist = PVE
::Cluster
::get_nodelist
();
135 my $members = PVE
::Cluster
::get_members
();
137 my $rrd = PVE
::Cluster
::rrd_dump
();
139 my $vmlist = PVE
::Cluster
::get_vmlist
() || {};
140 my $idlist = $vmlist->{ids
} || {};
143 # we try to generate 'numbers' by using "$X + 0"
144 foreach my $vmid (keys %$idlist) {
145 my $data = $idlist->{$vmid};
147 next if !$rpcenv->check($user, "/vms/$vmid", [ 'VM.Audit' ]);
150 id
=> "$data->{type}/$vmid",
152 node
=> $data->{node
},
153 type
=> $data->{type
},
156 if (my $d = $rrd->{"pve2-vm/$vmid"}) {
158 $entry->{uptime
} = ($d->[0] || 0) + 0;
159 $entry->{name
} = $d->[1];
161 $entry->{maxcpu
} = ($d->[3] || 0) + 0;
162 $entry->{cpu
} = ($d->[4] || 0) + 0;
163 $entry->{maxmem
} = ($d->[5] || 0) + 0;
164 $entry->{mem
} = ($d->[6] || 0) + 0;
165 $entry->{maxdisk
} = ($d->[7] || 0) + 0;
166 $entry->{disk
} = ($d->[8] || 0) + 0;
172 foreach my $node (@$nodelist) {
178 if (my $d = $rrd->{"pve2-node/$node"}) {
180 if (!$members || # no cluster
181 ($members->{$node} && $members->{$node}->{online
})) {
182 $entry->{uptime
} = ($d->[0] || 0) + 0;
183 $entry->{cpu
} = ($d->[4] || 0) + 0;
184 $entry->{mem
} = ($d->[7] || 0) + 0;
185 $entry->{disk
} = ($d->[11] || 0) + 0;
188 $entry->{maxcpu
} = ($d->[3] || 0) + 0;
189 $entry->{maxmem
} = ($d->[6] || 0) + 0;
190 $entry->{maxdisk
} = ($d->[10] || 0) + 0;
197 my $cfg = PVE
::Storage
::config
();
198 my @sids = PVE
::Storage
::storage_ids
($cfg);
200 foreach my $storeid (@sids) {
201 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
202 next if !$rpcenv->check($user, "/storage/$storeid", [ 'Datastore.Audit' ]);
203 # we create a entry for each node
204 foreach my $node (@$nodelist) {
205 next if !PVE
::Storage
::storage_check_enabled
($cfg, $storeid, $node, 1);
207 id
=> "storage/$node/$storeid",
213 if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) {
214 $entry->{maxdisk
} = ($d->[1] || 0) + 0;
215 $entry->{disk
} = ($d->[2] || 0) + 0;
226 __PACKAGE__-
>register_method({
230 description
=> "List recent tasks (cluster wide).",
231 permissions
=> { user
=> 'all' },
233 additionalProperties
=> 0,
241 upid
=> { type
=> 'string' },
248 my $rpcenv = PVE
::RPCEnvironment
::get
();
249 my $user = $rpcenv->get_user();
251 my $tlist = PVE
::Cluster
::get_tasklist
();
255 return $res if !$tlist;
257 my $all = $rpcenv->check($user, "/", [ 'Sys.Audit' ]);
259 foreach my $task (@$tlist) {
260 push @$res, $task if $all || ($task->{user
} eq $user);
266 __PACKAGE__-
>register_method({
267 name
=> 'get_options',
270 description
=> "Get datacenter options.",
273 privs
=> [ 'Sys.Audit' ],
276 additionalProperties
=> 0,
285 return PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
288 __PACKAGE__-
>register_method({
289 name
=> 'set_options',
292 description
=> "Set datacenter options.",
295 privs
=> [ 'Sys.Modify' ],
299 additionalProperties
=> 0,
300 properties
=> $dc_properties,
302 returns
=> { type
=> "null" },
306 my $filename = 'datacenter.cfg';
308 my $delete = extract_param
($param, 'delete');
312 my $conf = cfs_read_file
($filename);
314 foreach my $opt (keys %$param) {
315 $conf->{$opt} = $param->{$opt};
318 foreach my $opt (PVE
::Tools
::split_list
($delete)) {
319 delete $conf->{$opt};
322 cfs_write_file
($filename, $conf);
325 cfs_lock_file
($filename, undef, $code);
331 cfs_register_file
('vzdump',
335 my $vzdump_method_info = PVE
::API2
::VZDump-
>map_method_by_name('vzdump');
337 my $dowhash_to_dow = sub {
341 push @da, $num ?
1 : 'mon' if $d->{mon
};
342 push @da, $num ?
2 : 'tue' if $d->{tue
};
343 push @da, $num ?
3 : 'wed' if $d->{wed
};
344 push @da, $num ?
4 : 'thu' if $d->{thu
};
345 push @da, $num ?
5 : 'fri' if $d->{fri
};
346 push @da, $num ?
6 : 'sat' if $d->{sat
};
347 push @da, $num ?
7 : 'sun' if $d->{sun
};
349 return join ',', @da;
353 my ($dowstr, $noerr) = @_;
355 my $dowmap = {mon
=> 1, tue
=> 2, wed
=> 3, thu
=> 4,
356 fri
=> 5, sat
=> 6, sun
=> 7};
357 my $rdowmap = { '1' => 'mon', '2' => 'tue', '3' => 'wed', '4' => 'thu',
358 '5' => 'fri', '6' => 'sat', '7' => 'sun', '0' => 'sun'};
362 $dowstr = '1,2,3,4,5,6,7' if $dowstr eq '*';
364 foreach my $day (split (/,/, $dowstr)) {
365 if ($day =~ m/^(mon|tue|wed|thu|fri|sat|sun)-(mon|tue|wed|thu|fri|sat|sun)$/i) {
366 for (my $i = $dowmap->{lc($1)}; $i <= $dowmap->{lc($2)}; $i++) {
367 my $r = $rdowmap->{$i};
370 } elsif ($day =~ m/^(mon|tue|wed|thu|fri|sat|sun|[0-7])$/i) {
371 $day = $rdowmap->{$day} if $day =~ m/\d/;
372 $res->{lc($day)} = 1;
374 return undef if $noerr;
375 die "unable to parse day of week '$dowstr'\n";
383 my ($filename, $raw) = @_;
385 my $jobs = []; # correct jobs
387 my $ejobs = []; # mailfomerd lines
389 my $jid = 1; # we start at 1
391 my $digest = Digest
::SHA1
::sha1_hex
(defined($raw) ?
$raw : '');
393 while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
396 next if $line =~ m/^\#/;
397 next if $line =~ m/^\s*$/;
398 next if $line =~ m/^PATH\s*=/; # we always overwrite path
400 if ($line =~ m
|^(\d
+)\s
+(\d
+)\s
+\
*\s
+\
*\s
+(\S
+)\s
+root\s
+(/\S+/)?vzdump
(\s
+(.*))?
$|) {
402 my $minute = int($1);
407 my $dowhash = parse_dow
($dow, 1);
408 die "unable to parse day of week '$dow' in '$filename'\n" if !$dowhash;
410 my $args = [ split(/\s+/, $param)];
412 my $opts = PVE
::JSONSchema
::get_options
($vzdump_method_info->{parameters
},
413 $args, undef, undef, 'vmid');
415 $opts->{id
} = "$digest:$jid";
417 $opts->{hour
} = $hour;
418 $opts->{minute
} = $minute;
419 $opts->{dow
} = &$dowhash_to_dow($dowhash);
425 syslog
('err', "parse error in '$filename': $err");
426 push @$ejobs, { line
=> $line };
428 } elsif ($line =~ m
|^\S
+\s
+(\S
+)\s
+\S
+\s
+\S
+\s
+\S
+\s
+\S
+\s
+(\S
.*)$|) {
429 syslog
('err', "warning: malformed line in '$filename'");
430 push @$ejobs, { line
=> $line };
432 syslog
('err', "ignoring malformed line in '$filename'");
437 $res->{digest
} = $digest;
438 $res->{jobs
} = $jobs;
439 $res->{ejobs
} = $ejobs;
445 my ($filename, $cfg) = @_;
447 my $out = "# cluster wide vzdump cron schedule\n";
448 $out .= "# Atomatically generated file - do not edit\n\n";
449 $out .= "PATH=\"/usr/sbin:/usr/bin:/sbin:/bin\"\n\n";
451 my $jobs = $cfg->{jobs
} || [];
452 foreach my $job (@$jobs) {
453 my $dh = parse_dow
($job->{dow
});
455 if ($dh->{mon
} && $dh->{tue
} && $dh->{wed
} && $dh->{thu
} &&
456 $dh->{fri
} && $dh->{sat
} && $dh->{sun
}) {
459 $dow = &$dowhash_to_dow($dh, 1);
464 foreach my $p (keys %$job) {
465 next if $p eq 'id' || $p eq 'vmid' || $p eq 'hour' ||
466 $p eq 'minute' || $p eq 'dow';
467 $param .= " --$p " . $job->{$p};
470 $param .= $job->{vmid
} if $job->{vmid
};
472 $out .= sprintf "$job->{minute} $job->{hour} * * %-11s root vzdump$param\n", $dow;
475 my $ejobs = $cfg->{ejobs
} || [];
476 foreach my $job (@$ejobs) {
477 $out .= "$job->{line}\n" if $job->{line
};
483 __PACKAGE__-
>register_method({
487 description
=> "List vzdump backup schedule.",
489 additionalProperties
=> 0,
497 id
=> { type
=> 'string' },
500 links
=> [ { rel
=> 'child', href
=> "{id}" } ],
505 my $rpcenv = PVE
::RPCEnvironment
::get
();
506 my $user = $rpcenv->get_user();
508 my $data = cfs_read_file
('vzdump');
510 my $res = $data->{jobs
} || [];