]>
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);
14 use PVE
::API2
::Backup
;
15 use PVE
::API2
::HAConfig
;
18 use PVE
::RPCEnvironment
;
20 use base
qw(PVE::RESTHandler);
22 __PACKAGE__-
>register_method ({
23 subclass
=> "PVE::API2::Backup",
27 __PACKAGE__-
>register_method ({
28 subclass
=> "PVE::API2::HAConfig",
32 my $dc_schema = PVE
::Cluster
::get_datacenter_schema
();
35 type
=> 'string', format
=> 'pve-configid-list',
36 description
=> "A list of settings you want to delete.",
40 foreach my $opt (keys %{$dc_schema->{properties
}}) {
41 $dc_properties->{$opt} = $dc_schema->{properties
}->{$opt};
44 __PACKAGE__-
>register_method ({
48 description
=> "Cluster index.",
49 permissions
=> { user
=> 'all' },
51 additionalProperties
=> 0,
60 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
67 { name
=> 'options' },
68 { name
=> 'resources' },
78 __PACKAGE__-
>register_method({
82 description
=> "Read cluster log",
83 permissions
=> { user
=> 'all' },
85 additionalProperties
=> 0,
89 description
=> "Maximum number of entries.",
105 my $rpcenv = PVE
::RPCEnvironment
::get
();
107 my $max = $param->{max
} || 0;
108 my $user = $rpcenv->get_user();
110 my $admin = $rpcenv->check($user, "/", [ 'Sys.Syslog' ], 1);
112 my $loguser = $admin ?
'' : $user;
114 my $res = decode_json
(PVE
::Cluster
::get_cluster_log
($loguser, $max));
119 __PACKAGE__-
>register_method({
123 description
=> "Resources index (cluster wide).",
124 permissions
=> { user
=> 'all' },
126 additionalProperties
=> 0,
131 enum
=> ['vm', 'storage', 'node'],
146 my $rpcenv = PVE
::RPCEnvironment
::get
();
147 my $authuser = $rpcenv->get_user();
148 my $usercfg = $rpcenv->{user_cfg
};
152 my $nodelist = PVE
::Cluster
::get_nodelist
();
153 my $members = PVE
::Cluster
::get_members
();
155 my $rrd = PVE
::Cluster
::rrd_dump
();
157 my $vmlist = PVE
::Cluster
::get_vmlist
() || {};
158 my $idlist = $vmlist->{ids
} || {};
161 if (!$param->{type
} || $param->{type
} eq 'pool') {
162 foreach my $pool (keys %{$usercfg->{pools
}}) {
163 my $d = $usercfg->{pools
}->{$pool};
165 next if !$rpcenv->check($authuser, "/pool/$pool", [ 'Pool.Allocate' ], 1);
173 $pooldata->{$pool} = $entry;
179 # we try to generate 'numbers' by using "$X + 0"
180 if (!$param->{type
} || $param->{type
} eq 'vm') {
181 foreach my $vmid (keys %$idlist) {
183 my $data = $idlist->{$vmid};
184 my $entry = PVE
::API2Tools
::extract_vm_stats
($vmid, $data, $rrd);
185 if ($entry->{uptime
}) {
186 if (my $pool = $usercfg->{vms
}->{$vmid}) {
187 if (my $pe = $pooldata->{$pool}) {
188 $pe->{uptime
} = $entry->{uptime
} if !$pe->{uptime
} || $entry->{uptime
} > $pe->{uptime
};
189 $pe->{mem
} = 0 if !$pe->{mem
};
190 $pe->{mem
} += $entry->{mem
};
191 $pe->{maxmem
} = 0 if !$pe->{maxmem
};
192 $pe->{maxmem
} += $entry->{maxmem
};
193 $pe->{cpu
} = 0 if !$pe->{cpu
};
194 $pe->{cpu
} += $entry->{cpu
};
195 $pe->{maxcpu
} = 0 if !$pe->{maxcpu
};
196 $pe->{maxcpu
} += $entry->{maxcpu
};
201 next if !$rpcenv->check($authuser, "/vms/$vmid", [ 'VM.Audit' ], 1);
207 if (!$param->{type
} || $param->{type
} eq 'node') {
208 foreach my $node (@$nodelist) {
209 my $entry = PVE
::API2Tools
::extract_node_stats
($node, $members, $rrd);
214 if (!$param->{type
} || $param->{type
} eq 'storage') {
216 my $cfg = PVE
::Storage
::config
();
217 my @sids = PVE
::Storage
::storage_ids
($cfg);
219 foreach my $storeid (@sids) {
220 next if !$rpcenv->check($authuser, "/storage/$storeid", [ 'Datastore.Audit' ], 1);
222 my $scfg = PVE
::Storage
::storage_config
($cfg, $storeid);
223 # we create a entry for each node
224 foreach my $node (@$nodelist) {
225 next if !PVE
::Storage
::storage_check_enabled
($cfg, $storeid, $node, 1);
227 my $entry = PVE
::API2Tools
::extract_storage_stats
($storeid, $scfg, $node, $rrd);
236 __PACKAGE__-
>register_method({
240 description
=> "List recent tasks (cluster wide).",
241 permissions
=> { user
=> 'all' },
243 additionalProperties
=> 0,
251 upid
=> { type
=> 'string' },
258 my $rpcenv = PVE
::RPCEnvironment
::get
();
259 my $authuser = $rpcenv->get_user();
261 my $tlist = PVE
::Cluster
::get_tasklist
();
265 return $res if !$tlist;
267 my $all = $rpcenv->check($authuser, "/", [ 'Sys.Audit' ], 1);
269 foreach my $task (@$tlist) {
270 push @$res, $task if $all || ($task->{user
} eq $authuser);
276 __PACKAGE__-
>register_method({
277 name
=> 'get_options',
280 description
=> "Get datacenter options.",
282 check
=> ['perm', '/', [ 'Sys.Audit' ]],
285 additionalProperties
=> 0,
295 return PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
298 __PACKAGE__-
>register_method({
299 name
=> 'set_options',
302 description
=> "Set datacenter options.",
304 check
=> ['perm', '/', [ 'Sys.Modify' ]],
308 additionalProperties
=> 0,
309 properties
=> $dc_properties,
311 returns
=> { type
=> "null" },
315 my $filename = 'datacenter.cfg';
317 my $delete = extract_param
($param, 'delete');
321 my $conf = cfs_read_file
($filename);
323 foreach my $opt (keys %$param) {
324 $conf->{$opt} = $param->{$opt};
327 foreach my $opt (PVE
::Tools
::split_list
($delete)) {
328 delete $conf->{$opt};
331 cfs_write_file
($filename, $conf);
334 cfs_lock_file
($filename, undef, $code);
340 my $parse_clustat = sub {
341 my ($clinfo, $members, $rrd, $nodename, $raw) = @_;
343 my $createNode = sub {
344 my ($expat, $tag, %attrib) = @_;
345 my $node = { type
=> $tag, %attrib };
347 if ($tag eq 'node') {
348 my $name = $node->{name
};
349 return if !$name; # just to be sure
351 foreach my $key (qw(estranged local qdisk rgmanager rgmanager_master state)) {
352 $node->{$key} = int($node->{$key}) if defined($node->{$key});
354 $node->{nodeid
} = hex($node->{nodeid
}) if defined($node->{nodeid
});
357 $node->{id
} = "node/$node->{name}";
360 if (!$members) { # no cluster
361 if ($name eq $nodename) {
362 $pmxcfs = ($clinfo && $clinfo->{version
}) ?
1 : 0; # pmxcfs online ?
364 } elsif ($members->{$name}) {
365 $pmxcfs = $members->{$name}->{online
} ?
1 : 0
367 $node->{pmxcfs
} = $pmxcfs;
369 if ($members && $members->{$name}) {
370 if (my $ip = $members->{$name}->{ip
}) {
375 if (my $entry = PVE
::API2Tools
::extract_node_stats
($name, $members, $rrd)) {
376 $node->{level
} = $entry->{level
} || '';
379 } elsif ($tag eq 'group') {
380 my $name = $node->{name
};
381 return if !$name; # just to be sure
383 $node->{id
} = "group/$node->{name}";
401 $expat->{NodeList
} = [];
410 if ($extract_tags->{$tag}) {
411 my $node = &$createNode($expat, $tag, @_);
412 push @{$expat->{NodeList
}}, $node;
419 my $parser = new XML
::Parser
(Handlers
=> $handlers);
420 $data = $parser->parse($raw);
425 __PACKAGE__-
>register_method({
426 name
=> 'get_status',
429 description
=> "Get cluster status informations.",
431 check
=> ['perm', '/', [ 'Sys.Audit' ]],
435 additionalProperties
=> 0,
452 # we also add info from pmxcfs
453 my $clinfo = PVE
::Cluster
::get_clinfo
();
454 my $members = PVE
::Cluster
::get_members
();
455 my $nodename = PVE
::INotify
::nodename
();
456 my $rrd = PVE
::Cluster
::rrd_dump
();
459 my $cmd = ['clustat', '-x'];
461 PVE
::Tools
::run_command
($cmd, outfunc
=> sub { $out .= shift; });
462 return &$parse_clustat($clinfo, $members, $rrd, $nodename, $out);
464 # fake entry for local node if no cluster defined
465 my $pmxcfs = ($clinfo && $clinfo->{version
}) ?
1 : 0; # pmxcfs online ?
467 my $subinfo = PVE
::INotify
::read_file
('subscription');
468 my $sublevel = $subinfo->{level
} || '';
472 id
=> "node/$nodename",