]>
git.proxmox.com Git - pve-manager.git/blob - PVE/API2/Cluster.pm
1 package PVE
::API2
::Cluster
;
9 use PVE
::Tools
qw(extract_param);
11 use PVE
::Cluster
qw(cfs_register_file cfs_lock_file cfs_read_file cfs_write_file);
13 use PVE
::API2
::Backup
;
14 use PVE
::API2
::HAConfig
;
17 use PVE
::RPCEnvironment
;
19 use base
qw(PVE::RESTHandler);
21 __PACKAGE__-
>register_method ({
22 subclass
=> "PVE::API2::Backup",
26 __PACKAGE__-
>register_method ({
27 subclass
=> "PVE::API2::HAConfig",
31 my $dc_schema = PVE
::Cluster
::get_datacenter_schema
();
34 type
=> 'string', format
=> 'pve-configid-list',
35 description
=> "A list of settings you want to delete.",
39 foreach my $opt (keys %{$dc_schema->{properties
}}) {
40 $dc_properties->{$opt} = $dc_schema->{properties
}->{$opt};
43 __PACKAGE__-
>register_method ({
47 description
=> "Cluster index.",
48 permissions
=> { user
=> 'all' },
50 additionalProperties
=> 0,
59 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
66 { name
=> 'options' },
67 { name
=> 'resources' },
77 __PACKAGE__-
>register_method({
81 description
=> "Read cluster log",
82 permissions
=> { user
=> 'all' },
84 additionalProperties
=> 0,
88 description
=> "Maximum number of entries.",
104 my $rpcenv = PVE
::RPCEnvironment
::get
();
106 my $max = $param->{max
} || 0;
107 my $user = $rpcenv->get_user();
109 my $admin = $rpcenv->check($user, "/", [ 'Sys.Syslog' ]);
111 my $loguser = $admin ?
'' : $user;
113 my $res = decode_json
(PVE
::Cluster
::get_cluster_log
($loguser, $max));
118 __PACKAGE__-
>register_method({
122 description
=> "Resources index (cluster wide).",
123 permissions
=> { user
=> 'all' },
125 additionalProperties
=> 0,
130 enum
=> ['vm', 'storage', 'node'],
145 my $rpcenv = PVE
::RPCEnvironment
::get
();
146 my $user = $rpcenv->get_user();
150 my $nodelist = PVE
::Cluster
::get_nodelist
();
151 my $members = PVE
::Cluster
::get_members
();
153 my $rrd = PVE
::Cluster
::rrd_dump
();
155 my $vmlist = PVE
::Cluster
::get_vmlist
() || {};
156 my $idlist = $vmlist->{ids
} || {};
159 # we try to generate 'numbers' by using "$X + 0"
160 if (!$param->{type
} || $param->{type
} eq 'vm') {
161 foreach my $vmid (keys %$idlist) {
162 my $data = $idlist->{$vmid};
165 next if !$rpcenv->check($user, "/vms/$vmid", [ 'VM.Audit' ]);
168 id
=> "$data->{type}/$vmid",
170 node
=> $data->{node
},
171 type
=> $data->{type
},
174 if (my $d = $rrd->{"pve2-vm/$vmid"}) {
176 $entry->{uptime
} = ($d->[0] || 0) + 0;
177 $entry->{name
} = $d->[1];
179 $entry->{maxcpu
} = ($d->[3] || 0) + 0;
180 $entry->{cpu
} = ($d->[4] || 0) + 0;
181 $entry->{maxmem
} = ($d->[5] || 0) + 0;
182 $entry->{mem
} = ($d->[6] || 0) + 0;
183 $entry->{maxdisk
} = ($d->[7] || 0) + 0;
184 $entry->{disk
} = ($d->[8] || 0) + 0;
191 if (!$param->{type
} || $param->{type
} eq 'node') {
192 foreach my $node (@$nodelist) {
198 if (my $d = $rrd->{"pve2-node/$node"}) {
200 if (!$members || # no cluster
201 ($members->{$node} && $members->{$node}->{online
})) {
202 $entry->{uptime
} = ($d->[0] || 0) + 0;
203 $entry->{cpu
} = ($d->[4] || 0) + 0;
204 $entry->{mem
} = ($d->[7] || 0) + 0;
205 $entry->{disk
} = ($d->[11] || 0) + 0;
208 $entry->{maxcpu
} = ($d->[3] || 0) + 0;
209 $entry->{maxmem
} = ($d->[6] || 0) + 0;
210 $entry->{maxdisk
} = ($d->[10] || 0) + 0;
217 if (!$param->{type
} || $param->{type
} eq 'storage') {
219 my $cfg = PVE
::Storage
::config
();
220 my @sids = PVE
::Storage
::storage_ids
($cfg);
222 foreach my $storeid (@sids) {
223 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
224 next if !$rpcenv->check($user, "/storage/$storeid", [ 'Datastore.Audit' ]);
225 # we create a entry for each node
226 foreach my $node (@$nodelist) {
227 next if !PVE
::Storage
::storage_check_enabled
($cfg, $storeid, $node, 1);
229 id
=> "storage/$node/$storeid",
235 if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) {
236 $entry->{maxdisk
} = ($d->[1] || 0) + 0;
237 $entry->{disk
} = ($d->[2] || 0) + 0;
248 __PACKAGE__-
>register_method({
252 description
=> "List recent tasks (cluster wide).",
253 permissions
=> { user
=> 'all' },
255 additionalProperties
=> 0,
263 upid
=> { type
=> 'string' },
270 my $rpcenv = PVE
::RPCEnvironment
::get
();
271 my $user = $rpcenv->get_user();
273 my $tlist = PVE
::Cluster
::get_tasklist
();
277 return $res if !$tlist;
279 my $all = $rpcenv->check($user, "/", [ 'Sys.Audit' ]);
281 foreach my $task (@$tlist) {
282 push @$res, $task if $all || ($task->{user
} eq $user);
288 __PACKAGE__-
>register_method({
289 name
=> 'get_options',
292 description
=> "Get datacenter options.",
295 privs
=> [ 'Sys.Audit' ],
298 additionalProperties
=> 0,
307 return PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
310 __PACKAGE__-
>register_method({
311 name
=> 'set_options',
314 description
=> "Set datacenter options.",
317 privs
=> [ 'Sys.Modify' ],
321 additionalProperties
=> 0,
322 properties
=> $dc_properties,
324 returns
=> { type
=> "null" },
328 my $filename = 'datacenter.cfg';
330 my $delete = extract_param
($param, 'delete');
334 my $conf = cfs_read_file
($filename);
336 foreach my $opt (keys %$param) {
337 $conf->{$opt} = $param->{$opt};
340 foreach my $opt (PVE
::Tools
::split_list
($delete)) {
341 delete $conf->{$opt};
344 cfs_write_file
($filename, $conf);
347 cfs_lock_file
($filename, undef, $code);
353 my $parse_clustat = sub {
354 my ($clinfo, $members, $nodename, $raw) = @_;
356 my $createNode = sub {
357 my ($expat, $tag, %attrib) = @_;
358 my $node = { type
=> $tag, %attrib };
360 if ($tag eq 'node') {
361 my $name = $node->{name
};
362 return if !$name; # just to be sure
364 foreach my $key (qw(estranged local qdisk rgmanager rgmanager_master state)) {
365 $node->{$key} = int($node->{$key}) if defined($node->{$key});
367 $node->{nodeid
} = hex($node->{nodeid
}) if defined($node->{nodeid
});
370 $node->{id
} = "node/$node->{name}";
373 if (!$members) { # no cluster
374 if ($name eq $nodename) {
375 $pmxcfs = ($clinfo && $clinfo->{version
}) ?
1 : 0; # pmxcfs online ?
377 } elsif ($members->{$name}) {
378 $pmxcfs = $members->{$name}->{online
} ?
1 : 0
380 $node->{pmxcfs
} = $pmxcfs;
382 if ($members && $members->{$name}) {
383 if (my $ip = $members->{$name}->{ip
}) {
387 } elsif ($tag eq 'group') {
388 my $name = $node->{name
};
389 return if !$name; # just to be sure
391 $node->{id
} = "group/$node->{name}";
409 $expat->{NodeList
} = [];
418 if ($extract_tags->{$tag}) {
419 my $node = &$createNode($expat, $tag, @_);
420 push @{$expat->{NodeList
}}, $node;
427 my $parser = new XML
::Parser
(Handlers
=> $handlers);
428 $data = $parser->parse($raw);
433 __PACKAGE__-
>register_method({
434 name
=> 'get_status',
437 description
=> "Get cluster status informations.",
438 permissions
=> { user
=> 'all' },
441 additionalProperties
=> 0,
458 # we also add info from pmxcfs
459 my $clinfo = PVE
::Cluster
::get_clinfo
();
460 my $members = PVE
::Cluster
::get_members
();
461 my $nodename = PVE
::INotify
::nodename
();
464 my $cmd = ['clustat', '-x'];
466 PVE
::Tools
::run_command
($cmd, outfunc
=> sub { $out .= shift; });
467 return &$parse_clustat($clinfo, $members, $nodename, $out);
469 # fake entry for local node if no cluster defined
470 my $pmxcfs = ($clinfo && $clinfo->{version
}) ?
1 : 0; # pmxcfs online ?
473 id
=> "node/$nodename",