]>
git.proxmox.com Git - pmg-api.git/blob - PMG/API2/Nodes.pm
1 package PMG
::API2
::NodeInfo
;
5 use Time
::Local
qw(timegm_nocheck);
10 use PVE
::JSONSchema
qw(get_standard_option);
11 use PMG
::RESTEnvironment
;
18 use PMG
::API2
::Services
;
19 use PMG
::API2
::Network
;
20 use PMG
::API2
::ClamAV
;
21 use PMG
::API2
::Postfix
;
23 use base
qw(PVE::RESTHandler);
25 __PACKAGE__-
>register_method ({
26 subclass
=> "PMG::API2::Postfix",
30 __PACKAGE__-
>register_method ({
31 subclass
=> "PMG::API2::ClamAV",
35 __PACKAGE__-
>register_method ({
36 subclass
=> "PMG::API2::Network",
40 __PACKAGE__-
>register_method ({
41 subclass
=> "PMG::API2::Tasks",
45 __PACKAGE__-
>register_method ({
46 subclass
=> "PMG::API2::Services",
50 __PACKAGE__-
>register_method ({
54 permissions
=> { user
=> 'all' },
55 description
=> "Node index.",
57 additionalProperties
=> 0,
59 node
=> get_standard_option
('pve-node'),
68 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
75 { name
=> 'postfix' },
76 { name
=> 'services' },
81 { name
=> 'vncshell' },
82 { name
=> 'rrddata' },
88 __PACKAGE__-
>register_method({
92 protected
=> 1, # fixme: can we avoid that?
94 description
=> "Read node RRD statistics",
96 additionalProperties
=> 0,
98 node
=> get_standard_option
('pve-node'),
100 description
=> "Specify the time frame you are interested in.",
102 enum
=> [ 'hour', 'day', 'week', 'month', 'year' ],
105 description
=> "The RRD consolidation function",
107 enum
=> [ 'AVERAGE', 'MAX' ],
122 return PMG
::Utils
::create_rrd_data
(
123 "pmg-node-v1.rrd", $param->{timeframe
}, $param->{cf
});
127 __PACKAGE__-
>register_method({
131 description
=> "Read system log",
135 additionalProperties
=> 0,
137 node
=> get_standard_option
('pve-node'),
150 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
151 description
=> "Display all log since this date-time string.",
156 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
157 description
=> "Display all log until this date-time string.",
161 description
=> "Service ID",
174 description
=> "Line number",
178 description
=> "Line text",
187 my $restenv = PMG
::RESTEnvironment-
>get();
189 my $service = $param->{service
};
190 if ($service && $service eq 'postfix') {
191 $service = 'postfix@-';
194 my ($count, $lines) = PVE
::Tools
::dump_journal
(
195 $param->{start
}, $param->{limit
},
196 $param->{since
}, $param->{'until'}, $service);
198 $restenv->set_result_attrib('total', $count);
203 __PACKAGE__-
>register_method ({
208 description
=> "Creates a VNC Shell proxy.",
210 additionalProperties
=> 0,
212 node
=> get_standard_option
('pve-node'),
216 description
=> "use websocket instead of standard vnc.",
222 additionalProperties
=> 0,
224 user
=> { type
=> 'string' },
225 ticket
=> { type
=> 'string' },
226 port
=> { type
=> 'integer' },
227 upid
=> { type
=> 'string' },
233 my $node = $param->{node
};
235 # we only implement the websocket based VNC here
236 my $websocket = $param->{websocket
} // 1;
237 die "standard VNC not implemented" if !$websocket;
239 my $authpath = "/nodes/$node";
241 my $restenv = PMG
::RESTEnvironment-
>get();
242 my $user = $restenv->get_user();
244 my $ticket = PMG
::Ticket
::assemble_vnc_ticket
($user, $authpath);
246 my $family = PVE
::Tools
::get_host_address_family
($node);
247 my $port = PVE
::Tools
::next_vnc_port
($family);
251 if ($user eq 'root@pam') {
252 $shcmd = [ '/bin/login', '-f', 'root' ];
254 $shcmd = [ '/bin/login' ];
257 my $cmd = ['/usr/bin/vncterm', '-rfbport', $port,
258 '-timeout', 10, '-notls', '-listen', 'localhost',
264 syslog
('info', "starting vnc proxy $upid\n");
266 my $cmdstr = join (' ', @$cmd);
267 syslog
('info', "launch command: $cmdstr");
270 foreach my $k (keys %ENV) {
271 next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME';
276 $ENV{PVE_VNC_TICKET
} = $ticket; # pass ticket to vncterm
278 PVE
::Tools
::run_command
($cmd, errmsg
=> "vncterm failed");
287 my $upid = $restenv->fork_worker('vncshell', "", $user, $realcmd);
289 PVE
::Tools
::wait_for_vnc_port
($port);
299 __PACKAGE__-
>register_method({
300 name
=> 'vncwebsocket',
301 path
=> 'vncwebsocket',
303 description
=> "Opens a weksocket for VNC traffic.",
305 additionalProperties
=> 0,
307 node
=> get_standard_option
('pve-node'),
309 description
=> "Ticket from previous call to vncproxy.",
314 description
=> "Port number returned by previous vncproxy call.",
324 port
=> { type
=> 'string' },
330 my $authpath = "/nodes/$param->{node}";
332 my $restenv = PMG
::RESTEnvironment-
>get();
333 my $user = $restenv->get_user();
335 PMG
::Ticket
::verify_vnc_ticket
($param->{vncticket
}, $user, $authpath);
337 my $port = $param->{port
};
339 return { port
=> $port };
342 __PACKAGE__-
>register_method({
346 description
=> "Read DNS settings.",
349 additionalProperties
=> 0,
351 node
=> get_standard_option
('pve-node'),
356 additionalProperties
=> 0,
359 description
=> "Search domain for host-name lookup.",
364 description
=> 'First name server IP address.',
369 description
=> 'Second name server IP address.',
374 description
=> 'Third name server IP address.',
383 my $res = PVE
::INotify
::read_file
('resolvconf');
388 __PACKAGE__-
>register_method({
389 name
=> 'update_dns',
392 description
=> "Write DNS settings.",
396 additionalProperties
=> 0,
398 node
=> get_standard_option
('pve-node'),
400 description
=> "Search domain for host-name lookup.",
404 description
=> 'First name server IP address.',
405 type
=> 'string', format
=> 'ip',
409 description
=> 'Second name server IP address.',
410 type
=> 'string', format
=> 'ip',
414 description
=> 'Third name server IP address.',
415 type
=> 'string', format
=> 'ip',
420 returns
=> { type
=> "null" },
424 PVE
::INotify
::update_file
('resolvconf', $param);
430 __PACKAGE__-
>register_method({
434 description
=> "Read server time and time zone settings.",
437 additionalProperties
=> 0,
439 node
=> get_standard_option
('pve-node'),
444 additionalProperties
=> 0,
447 description
=> "Time zone",
451 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
453 minimum
=> 1297163644,
456 description
=> "Seconds since 1970-01-01 00:00:00 (local time)",
458 minimum
=> 1297163644,
466 my $ltime = timegm_nocheck
(localtime($ctime));
468 timezone
=> PVE
::INotify
::read_file
('timezone'),
476 __PACKAGE__-
>register_method({
477 name
=> 'set_timezone',
480 description
=> "Set time zone.",
484 additionalProperties
=> 0,
486 node
=> get_standard_option
('pve-node'),
488 description
=> "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
493 returns
=> { type
=> "null" },
497 PVE
::INotify
::write_file
('timezone', $param->{timezone
});
502 __PACKAGE__-
>register_method({
506 description
=> "Read server status. This is used by the cluster manager to test the node health.",
510 additionalProperties
=> 0,
512 node
=> get_standard_option
('pve-node'),
517 additionalProperties
=> 1,
520 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
522 minimum
=> 1297163644,
525 description
=> "The uptime of the system in seconds.",
530 description
=> "Database is synced with other nodes.",
538 my $restenv = PMG
::RESTEnvironment-
>get();
539 my $cinfo = $restenv->{cinfo
};
543 my $res = { time => $ctime, insync
=> 1 };
545 my $si = PMG
::DBTools
::cluster_sync_status
($cinfo);
546 foreach my $cid (keys %$si) {
547 my $lastsync = $si->{$cid};
548 my $sdiff = $ctime - $lastsync;
549 $sdiff = 0 if $sdiff < 0;
550 $res->{insync
} = 0 if $sdiff > (60*3);
553 my ($uptime, $idle) = PVE
::ProcFSTools
::read_proc_uptime
();
554 $res->{uptime
} = $uptime;
556 my ($avg1, $avg5, $avg15) = PVE
::ProcFSTools
::read_loadavg
();
557 $res->{loadavg
} = [ $avg1, $avg5, $avg15];
559 my ($sysname, $nodename, $release, $version, $machine) = POSIX
::uname
();
561 $res->{kversion
} = "$sysname $release $version";
563 $res->{cpuinfo
} = PVE
::ProcFSTools
::read_cpuinfo
();
565 my $stat = PVE
::ProcFSTools
::read_proc_stat
();
566 $res->{cpu
} = $stat->{cpu
};
567 $res->{wait} = $stat->{wait};
569 my $meminfo = PVE
::ProcFSTools
::read_meminfo
();
571 free
=> $meminfo->{memfree
},
572 total
=> $meminfo->{memtotal
},
573 used
=> $meminfo->{memused
},
577 free
=> $meminfo->{swapfree
},
578 total
=> $meminfo->{swaptotal
},
579 used
=> $meminfo->{swapused
},
582 $res->{pmgversion
} = PMG
::pmgcfg
::package() . "/" .
583 PMG
::pmgcfg
::version_text
();
585 my $dinfo = df
('/', 1); # output is bytes
588 total
=> $dinfo->{blocks
},
589 avail
=> $dinfo->{bavail
},
590 used
=> $dinfo->{used
},
591 free
=> $dinfo->{bavail
} - $dinfo->{used
},
598 package PMG
::API2
::Nodes
;
603 use PVE
::RESTHandler
;
604 use PVE
::JSONSchema
qw(get_standard_option);
606 use PMG
::RESTEnvironment
;
608 use base
qw(PVE::RESTHandler);
610 __PACKAGE__-
>register_method ({
611 subclass
=> "PMG::API2::NodeInfo",
615 __PACKAGE__-
>register_method ({
619 permissions
=> { user
=> 'all' },
620 description
=> "Cluster node index.",
622 additionalProperties
=> 0,
631 links
=> [ { rel
=> 'child', href
=> "{node}" } ],
636 my $nodename = PVE
::INotify
::nodename
();
638 my $res = [ { node
=> $nodename } ];
642 $done->{$nodename} = 1;
644 my $restenv = PMG
::RESTEnvironment-
>get();
645 my $cinfo = $restenv->{cinfo
};
647 foreach my $ni (values %{$cinfo->{ids
}}) {
648 push @$res, { node
=> $ni->{name
} } if !$done->{$ni->{name
}};
649 $done->{$ni->{name
}} = 1;