]>
git.proxmox.com Git - pmg-api.git/blob - PMG/API2/Nodes.pm
1 package PMG
::API2
::NodeInfo
;
5 use Time
::Local
qw(timegm_nocheck);
11 use PVE
::JSONSchema
qw(get_standard_option);
12 use PMG
::RESTEnvironment
;
18 use PMG
::API2
::Subscription
;
21 use PMG
::API2
::Services
;
22 use PMG
::API2
::Network
;
23 use PMG
::API2
::ClamAV
;
24 use PMG
::API2
::SpamAssassin
;
25 use PMG
::API2
::Postfix
;
26 use PMG
::API2
::MailTracker
;
28 use base
qw(PVE::RESTHandler);
30 __PACKAGE__-
>register_method ({
31 subclass
=> "PMG::API2::Postfix",
35 __PACKAGE__-
>register_method ({
36 subclass
=> "PMG::API2::ClamAV",
40 __PACKAGE__-
>register_method ({
41 subclass
=> "PMG::API2::SpamAssassin",
42 path
=> 'spamassassin',
45 __PACKAGE__-
>register_method ({
46 subclass
=> "PMG::API2::Network",
50 __PACKAGE__-
>register_method ({
51 subclass
=> "PMG::API2::Tasks",
55 __PACKAGE__-
>register_method ({
56 subclass
=> "PMG::API2::Services",
60 __PACKAGE__-
>register_method ({
61 subclass
=> "PMG::API2::Subscription",
62 path
=> 'subscription',
65 __PACKAGE__-
>register_method ({
66 subclass
=> "PMG::API2::APT",
70 __PACKAGE__-
>register_method ({
71 subclass
=> "PMG::API2::MailTracker",
75 __PACKAGE__-
>register_method ({
79 permissions
=> { user
=> 'all' },
80 description
=> "Node index.",
82 additionalProperties
=> 0,
84 node
=> get_standard_option
('pve-node'),
93 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
100 { name
=> 'clamav' },
101 { name
=> 'spamassassin' },
102 { name
=> 'postfix' },
103 { name
=> 'services' },
104 { name
=> 'syslog' },
106 { name
=> 'tracker' },
108 { name
=> 'status' },
109 { name
=> 'subscription' },
110 { name
=> 'vncshell' },
111 { name
=> 'rrddata' },
117 __PACKAGE__-
>register_method({
121 protected
=> 1, # fixme: can we avoid that?
123 permissions
=> { check
=> [ 'admin', 'audit' ] },
124 description
=> "Read node RRD statistics",
126 additionalProperties
=> 0,
128 node
=> get_standard_option
('pve-node'),
130 description
=> "Specify the time frame you are interested in.",
132 enum
=> [ 'hour', 'day', 'week', 'month', 'year' ],
135 description
=> "The RRD consolidation function",
137 enum
=> [ 'AVERAGE', 'MAX' ],
152 return PMG
::Utils
::create_rrd_data
(
153 "pmg-node-v1.rrd", $param->{timeframe
}, $param->{cf
});
157 __PACKAGE__-
>register_method({
161 description
=> "Read system log",
164 permissions
=> { check
=> [ 'admin', 'audit' ] },
166 additionalProperties
=> 0,
168 node
=> get_standard_option
('pve-node'),
181 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
182 description
=> "Display all log since this date-time string.",
187 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
188 description
=> "Display all log until this date-time string.",
192 description
=> "Service ID",
205 description
=> "Line number",
209 description
=> "Line text",
218 my $restenv = PMG
::RESTEnvironment-
>get();
220 my $service = $param->{service
};
221 $service = PMG
::Utils
::lookup_real_service_name
($service)
224 my ($count, $lines) = PVE
::Tools
::dump_journal
(
225 $param->{start
}, $param->{limit
},
226 $param->{since
}, $param->{'until'}, $service);
228 $restenv->set_result_attrib('total', $count);
233 __PACKAGE__-
>register_method ({
238 description
=> "Creates a VNC Shell proxy.",
240 additionalProperties
=> 0,
242 node
=> get_standard_option
('pve-node'),
245 description
=> "Run 'apt-get dist-upgrade' instead of normal shell.",
252 description
=> "use websocket instead of standard vnc.",
258 additionalProperties
=> 0,
260 user
=> { type
=> 'string' },
261 ticket
=> { type
=> 'string' },
262 port
=> { type
=> 'integer' },
263 upid
=> { type
=> 'string' },
269 my $node = $param->{node
};
271 if ($node ne PVE
::INotify
::nodename
()) {
272 die "vncproxy to remote node not implemented";
275 # we only implement the websocket based VNC here
276 my $websocket = $param->{websocket
} // 1;
277 die "standard VNC not implemented" if !$websocket;
279 my $authpath = "/nodes/$node";
281 my $restenv = PMG
::RESTEnvironment-
>get();
282 my $user = $restenv->get_user();
284 raise_perm_exc
('user != root@pam') if $param->{upgrade
} && $user ne 'root@pam';
286 my $ticket = PMG
::Ticket
::assemble_vnc_ticket
($user, $authpath);
288 my $family = PVE
::Tools
::get_host_address_family
($node);
289 my $port = PVE
::Tools
::next_vnc_port
($family);
293 if ($user eq 'root@pam') {
294 if ($param->{upgrade
}) {
295 my $upgradecmd = "pmgupgrade --shell";
296 # $upgradecmd = PVE::Tools::shellquote($upgradecmd) if $remip;
297 $shcmd = [ '/bin/bash', '-c', $upgradecmd ];
299 $shcmd = [ '/bin/login', '-f', 'root' ];
302 $shcmd = [ '/bin/login' ];
305 my $cmd = ['/usr/bin/vncterm', '-rfbport', $port,
306 '-timeout', 10, '-notls', '-listen', 'localhost',
312 syslog
('info', "starting vnc proxy $upid\n");
314 my $cmdstr = join (' ', @$cmd);
315 syslog
('info', "launch command: $cmdstr");
318 foreach my $k (keys %ENV) {
319 next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME';
324 $ENV{PVE_VNC_TICKET
} = $ticket; # pass ticket to vncterm
326 PVE
::Tools
::run_command
($cmd, errmsg
=> "vncterm failed");
335 my $upid = $restenv->fork_worker('vncshell', "", $user, $realcmd);
337 PVE
::Tools
::wait_for_vnc_port
($port);
347 __PACKAGE__-
>register_method({
348 name
=> 'vncwebsocket',
349 path
=> 'vncwebsocket',
351 description
=> "Opens a weksocket for VNC traffic.",
353 additionalProperties
=> 0,
355 node
=> get_standard_option
('pve-node'),
357 description
=> "Ticket from previous call to vncproxy.",
362 description
=> "Port number returned by previous vncproxy call.",
372 port
=> { type
=> 'string' },
378 my $authpath = "/nodes/$param->{node}";
380 my $restenv = PMG
::RESTEnvironment-
>get();
381 my $user = $restenv->get_user();
383 PMG
::Ticket
::verify_vnc_ticket
($param->{vncticket
}, $user, $authpath);
385 my $port = $param->{port
};
387 return { port
=> $port };
390 __PACKAGE__-
>register_method({
394 description
=> "Read DNS settings.",
396 permissions
=> { check
=> [ 'admin', 'audit' ] },
398 additionalProperties
=> 0,
400 node
=> get_standard_option
('pve-node'),
405 additionalProperties
=> 0,
408 description
=> "Search domain for host-name lookup.",
413 description
=> 'First name server IP address.',
418 description
=> 'Second name server IP address.',
423 description
=> 'Third name server IP address.',
432 my $res = PVE
::INotify
::read_file
('resolvconf');
437 __PACKAGE__-
>register_method({
438 name
=> 'update_dns',
441 description
=> "Write DNS settings.",
445 additionalProperties
=> 0,
447 node
=> get_standard_option
('pve-node'),
449 description
=> "Search domain for host-name lookup.",
453 description
=> 'First name server IP address.',
454 type
=> 'string', format
=> 'ip',
458 description
=> 'Second name server IP address.',
459 type
=> 'string', format
=> 'ip',
463 description
=> 'Third name server IP address.',
464 type
=> 'string', format
=> 'ip',
469 returns
=> { type
=> "null" },
473 PVE
::INotify
::update_file
('resolvconf', $param);
479 __PACKAGE__-
>register_method({
483 description
=> "Read server time and time zone settings.",
485 permissions
=> { check
=> [ 'admin', 'audit' ] },
487 additionalProperties
=> 0,
489 node
=> get_standard_option
('pve-node'),
494 additionalProperties
=> 0,
497 description
=> "Time zone",
501 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
503 minimum
=> 1297163644,
506 description
=> "Seconds since 1970-01-01 00:00:00 (local time)",
508 minimum
=> 1297163644,
516 my $ltime = timegm_nocheck
(localtime($ctime));
518 timezone
=> PVE
::INotify
::read_file
('timezone'),
526 __PACKAGE__-
>register_method({
527 name
=> 'set_timezone',
530 description
=> "Set time zone.",
534 additionalProperties
=> 0,
536 node
=> get_standard_option
('pve-node'),
538 description
=> "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
543 returns
=> { type
=> "null" },
547 PVE
::INotify
::write_file
('timezone', $param->{timezone
});
552 __PACKAGE__-
>register_method({
556 description
=> "Read server status. This is used by the cluster manager to test the node health.",
560 additionalProperties
=> 0,
562 node
=> get_standard_option
('pve-node'),
567 additionalProperties
=> 1,
570 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
572 minimum
=> 1297163644,
575 description
=> "The uptime of the system in seconds.",
580 description
=> "Database is synced with other nodes.",
588 my $restenv = PMG
::RESTEnvironment-
>get();
589 my $cinfo = $restenv->{cinfo
};
593 my $res = { time => $ctime, insync
=> 1 };
595 my $si = PMG
::DBTools
::cluster_sync_status
($cinfo);
596 foreach my $cid (keys %$si) {
597 my $lastsync = $si->{$cid};
598 my $sdiff = $ctime - $lastsync;
599 $sdiff = 0 if $sdiff < 0;
600 $res->{insync
} = 0 if $sdiff > (60*3);
603 my ($uptime, $idle) = PVE
::ProcFSTools
::read_proc_uptime
();
604 $res->{uptime
} = $uptime;
606 my ($avg1, $avg5, $avg15) = PVE
::ProcFSTools
::read_loadavg
();
607 $res->{loadavg
} = [ $avg1, $avg5, $avg15];
609 my ($sysname, $nodename, $release, $version, $machine) = POSIX
::uname
();
611 $res->{kversion
} = "$sysname $release $version";
613 $res->{cpuinfo
} = PVE
::ProcFSTools
::read_cpuinfo
();
615 my $stat = PVE
::ProcFSTools
::read_proc_stat
();
616 $res->{cpu
} = $stat->{cpu
};
617 $res->{wait} = $stat->{wait};
619 my $meminfo = PVE
::ProcFSTools
::read_meminfo
();
621 free
=> $meminfo->{memfree
},
622 total
=> $meminfo->{memtotal
},
623 used
=> $meminfo->{memused
},
627 free
=> $meminfo->{swapfree
},
628 total
=> $meminfo->{swaptotal
},
629 used
=> $meminfo->{swapused
},
632 $res->{pmgversion
} = PMG
::pmgcfg
::package() . "/" .
633 PMG
::pmgcfg
::version_text
();
635 my $dinfo = df
('/', 1); # output is bytes
638 total
=> $dinfo->{blocks
},
639 avail
=> $dinfo->{bavail
},
640 used
=> $dinfo->{used
},
641 free
=> $dinfo->{blocks
} - $dinfo->{used
},
644 if (my $subinfo = PVE
::INotify
::read_file
('subscription')) {
645 if (my $level = $subinfo->{level
}) {
646 $res->{level
} = $level;
654 package PMG
::API2
::Nodes
;
659 use PVE
::RESTHandler
;
660 use PVE
::JSONSchema
qw(get_standard_option);
662 use PMG
::RESTEnvironment
;
664 use base
qw(PVE::RESTHandler);
666 __PACKAGE__-
>register_method ({
667 subclass
=> "PMG::API2::NodeInfo",
671 __PACKAGE__-
>register_method ({
675 permissions
=> { user
=> 'all' },
676 description
=> "Cluster node index.",
678 additionalProperties
=> 0,
687 links
=> [ { rel
=> 'child', href
=> "{node}" } ],
692 my $nodename = PVE
::INotify
::nodename
();
694 my $res = [ { node
=> $nodename } ];
698 $done->{$nodename} = 1;
700 my $restenv = PMG
::RESTEnvironment-
>get();
701 my $cinfo = $restenv->{cinfo
};
703 foreach my $ni (values %{$cinfo->{ids
}}) {
704 push @$res, { node
=> $ni->{name
} } if !$done->{$ni->{name
}};
705 $done->{$ni->{name
}} = 1;