]>
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
;
27 use PMG
::API2
::Backup
;
29 use base
qw(PVE::RESTHandler);
31 __PACKAGE__-
>register_method ({
32 subclass
=> "PMG::API2::Postfix",
36 __PACKAGE__-
>register_method ({
37 subclass
=> "PMG::API2::ClamAV",
41 __PACKAGE__-
>register_method ({
42 subclass
=> "PMG::API2::SpamAssassin",
43 path
=> 'spamassassin',
46 __PACKAGE__-
>register_method ({
47 subclass
=> "PMG::API2::Network",
51 __PACKAGE__-
>register_method ({
52 subclass
=> "PMG::API2::Tasks",
56 __PACKAGE__-
>register_method ({
57 subclass
=> "PMG::API2::Services",
61 __PACKAGE__-
>register_method ({
62 subclass
=> "PMG::API2::Subscription",
63 path
=> 'subscription',
66 __PACKAGE__-
>register_method ({
67 subclass
=> "PMG::API2::APT",
71 __PACKAGE__-
>register_method ({
72 subclass
=> "PMG::API2::MailTracker",
76 __PACKAGE__-
>register_method ({
77 subclass
=> "PMG::API2::Backup",
81 __PACKAGE__-
>register_method ({
85 permissions
=> { user
=> 'all' },
86 description
=> "Node index.",
88 additionalProperties
=> 0,
90 node
=> get_standard_option
('pve-node'),
99 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
106 { name
=> 'backup' },
107 { name
=> 'clamav' },
108 { name
=> 'spamassassin' },
109 { name
=> 'postfix' },
110 { name
=> 'services' },
111 { name
=> 'syslog' },
113 { name
=> 'tracker' },
115 { name
=> 'status' },
116 { name
=> 'subscription' },
117 { name
=> 'termproxy' },
118 { name
=> 'rrddata' },
124 __PACKAGE__-
>register_method({
128 protected
=> 1, # fixme: can we avoid that?
130 permissions
=> { check
=> [ 'admin', 'audit' ] },
131 description
=> "Read node RRD statistics",
133 additionalProperties
=> 0,
135 node
=> get_standard_option
('pve-node'),
137 description
=> "Specify the time frame you are interested in.",
139 enum
=> [ 'hour', 'day', 'week', 'month', 'year' ],
142 description
=> "The RRD consolidation function",
144 enum
=> [ 'AVERAGE', 'MAX' ],
159 return PMG
::Utils
::create_rrd_data
(
160 "pmg-node-v1.rrd", $param->{timeframe
}, $param->{cf
});
164 __PACKAGE__-
>register_method({
168 description
=> "Read system log",
171 permissions
=> { check
=> [ 'admin', 'audit' ] },
173 additionalProperties
=> 0,
175 node
=> get_standard_option
('pve-node'),
188 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
189 description
=> "Display all log since this date-time string.",
194 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
195 description
=> "Display all log until this date-time string.",
199 description
=> "Service ID",
212 description
=> "Line number",
216 description
=> "Line text",
225 my $restenv = PMG
::RESTEnvironment-
>get();
227 my $service = $param->{service
};
228 $service = PMG
::Utils
::lookup_real_service_name
($service)
231 my ($count, $lines) = PVE
::Tools
::dump_journal
(
232 $param->{start
}, $param->{limit
},
233 $param->{since
}, $param->{'until'}, $service);
235 $restenv->set_result_attrib('total', $count);
241 __PACKAGE__-
>register_method ({
245 permissions
=> { check
=> [ 'admin' ] },
247 description
=> "Creates a Terminal proxy.",
249 additionalProperties
=> 0,
251 node
=> get_standard_option
('pve-node'),
254 description
=> "Run 'apt-get dist-upgrade' instead of normal shell.",
261 additionalProperties
=> 0,
263 user
=> { type
=> 'string' },
264 ticket
=> { type
=> 'string' },
265 port
=> { type
=> 'integer' },
266 upid
=> { type
=> 'string' },
272 my $node = $param->{node
};
274 if ($node ne PVE
::INotify
::nodename
()) {
275 die "termproxy to remote node not implemented";
278 my $authpath = "/nodes/$node";
280 my $restenv = PMG
::RESTEnvironment-
>get();
281 my $user = $restenv->get_user();
283 raise_perm_exc
('user != root@pam') if $param->{upgrade
} && $user ne 'root@pam';
285 my $ticket = PMG
::Ticket
::assemble_vnc_ticket
($user, $authpath);
287 my $family = PVE
::Tools
::get_host_address_family
($node);
288 my $port = PVE
::Tools
::next_vnc_port
($family);
292 if ($user eq 'root@pam') {
293 if ($param->{upgrade
}) {
294 my $upgradecmd = "pmgupgrade --shell";
295 # $upgradecmd = PVE::Tools::shellquote($upgradecmd) if $remip;
296 $shcmd = [ '/bin/bash', '-c', $upgradecmd ];
298 $shcmd = [ '/bin/login', '-f', 'root' ];
301 $shcmd = [ '/bin/login' ];
304 my $cmd = ['/usr/bin/termproxy', $port, '--path', $authpath,
310 syslog
('info', "starting termproxy $upid\n");
312 my $cmdstr = join (' ', @$cmd);
313 syslog
('info', "launch command: $cmdstr");
315 PVE
::Tools
::run_command
($cmd);
320 my $upid = $restenv->fork_worker('termproxy', "", $user, $realcmd);
322 PVE
::Tools
::wait_for_vnc_port
($port);
332 __PACKAGE__-
>register_method({
333 name
=> 'vncwebsocket',
334 path
=> 'vncwebsocket',
336 permissions
=> { check
=> [ 'admin' ] },
337 description
=> "Opens a weksocket for VNC traffic.",
339 additionalProperties
=> 0,
341 node
=> get_standard_option
('pve-node'),
343 description
=> "Ticket from previous call to vncproxy.",
348 description
=> "Port number returned by previous vncproxy call.",
358 port
=> { type
=> 'string' },
364 my $authpath = "/nodes/$param->{node}";
366 my $restenv = PMG
::RESTEnvironment-
>get();
367 my $user = $restenv->get_user();
369 PMG
::Ticket
::verify_vnc_ticket
($param->{vncticket
}, $user, $authpath);
371 my $port = $param->{port
};
373 return { port
=> $port };
376 __PACKAGE__-
>register_method({
380 description
=> "Read DNS settings.",
382 permissions
=> { check
=> [ 'admin', 'audit' ] },
384 additionalProperties
=> 0,
386 node
=> get_standard_option
('pve-node'),
391 additionalProperties
=> 0,
394 description
=> "Search domain for host-name lookup.",
399 description
=> 'First name server IP address.',
404 description
=> 'Second name server IP address.',
409 description
=> 'Third name server IP address.',
418 my $res = PVE
::INotify
::read_file
('resolvconf');
423 __PACKAGE__-
>register_method({
424 name
=> 'update_dns',
427 description
=> "Write DNS settings.",
431 additionalProperties
=> 0,
433 node
=> get_standard_option
('pve-node'),
435 description
=> "Search domain for host-name lookup.",
439 description
=> 'First name server IP address.',
440 type
=> 'string', format
=> 'ip',
444 description
=> 'Second name server IP address.',
445 type
=> 'string', format
=> 'ip',
449 description
=> 'Third name server IP address.',
450 type
=> 'string', format
=> 'ip',
455 returns
=> { type
=> "null" },
459 PVE
::INotify
::update_file
('resolvconf', $param);
465 __PACKAGE__-
>register_method({
469 description
=> "Read server time and time zone settings.",
471 permissions
=> { check
=> [ 'admin', 'audit' ] },
473 additionalProperties
=> 0,
475 node
=> get_standard_option
('pve-node'),
480 additionalProperties
=> 0,
483 description
=> "Time zone",
487 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
489 minimum
=> 1297163644,
492 description
=> "Seconds since 1970-01-01 00:00:00 (local time)",
494 minimum
=> 1297163644,
502 my $ltime = timegm_nocheck
(localtime($ctime));
504 timezone
=> PVE
::INotify
::read_file
('timezone'),
512 __PACKAGE__-
>register_method({
513 name
=> 'set_timezone',
516 description
=> "Set time zone.",
520 additionalProperties
=> 0,
522 node
=> get_standard_option
('pve-node'),
524 description
=> "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
529 returns
=> { type
=> "null" },
533 PVE
::INotify
::write_file
('timezone', $param->{timezone
});
538 __PACKAGE__-
>register_method({
542 description
=> "Read server status. This is used by the cluster manager to test the node health.",
546 additionalProperties
=> 0,
548 node
=> get_standard_option
('pve-node'),
553 additionalProperties
=> 1,
556 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
558 minimum
=> 1297163644,
561 description
=> "The uptime of the system in seconds.",
566 description
=> "Database is synced with other nodes.",
574 my $restenv = PMG
::RESTEnvironment-
>get();
575 my $cinfo = $restenv->{cinfo
};
579 my $res = { time => $ctime, insync
=> 1 };
581 my $si = PMG
::DBTools
::cluster_sync_status
($cinfo);
582 foreach my $cid (keys %$si) {
583 my $lastsync = $si->{$cid};
584 my $sdiff = $ctime - $lastsync;
585 $sdiff = 0 if $sdiff < 0;
586 $res->{insync
} = 0 if $sdiff > (60*3);
589 my ($uptime, $idle) = PVE
::ProcFSTools
::read_proc_uptime
();
590 $res->{uptime
} = $uptime;
592 my ($avg1, $avg5, $avg15) = PVE
::ProcFSTools
::read_loadavg
();
593 $res->{loadavg
} = [ $avg1, $avg5, $avg15];
595 my ($sysname, $nodename, $release, $version, $machine) = POSIX
::uname
();
597 $res->{kversion
} = "$sysname $release $version";
599 $res->{cpuinfo
} = PVE
::ProcFSTools
::read_cpuinfo
();
601 my $stat = PVE
::ProcFSTools
::read_proc_stat
();
602 $res->{cpu
} = $stat->{cpu
};
603 $res->{wait} = $stat->{wait};
605 my $meminfo = PVE
::ProcFSTools
::read_meminfo
();
607 free
=> $meminfo->{memfree
},
608 total
=> $meminfo->{memtotal
},
609 used
=> $meminfo->{memused
},
613 free
=> $meminfo->{swapfree
},
614 total
=> $meminfo->{swaptotal
},
615 used
=> $meminfo->{swapused
},
618 $res->{pmgversion
} = PMG
::pmgcfg
::package() . "/" .
619 PMG
::pmgcfg
::version_text
();
621 my $dinfo = df
('/', 1); # output is bytes
624 total
=> $dinfo->{blocks
},
625 avail
=> $dinfo->{bavail
},
626 used
=> $dinfo->{used
},
627 free
=> $dinfo->{blocks
} - $dinfo->{used
},
630 if (my $subinfo = PVE
::INotify
::read_file
('subscription')) {
631 if (my $level = $subinfo->{level
}) {
632 $res->{level
} = $level;
639 __PACKAGE__-
>register_method({
643 permissions
=> { check
=> [ 'admin' ] },
645 description
=> "Reboot or shutdown a node.",
648 additionalProperties
=> 0,
650 node
=> get_standard_option
('pve-node'),
652 description
=> "Specify the command.",
654 enum
=> [qw(reboot shutdown)],
658 returns
=> { type
=> "null" },
662 if ($param->{command
} eq 'reboot') {
663 system ("(sleep 2;/sbin/reboot)&");
664 } elsif ($param->{command
} eq 'shutdown') {
665 system ("(sleep 2;/sbin/poweroff)&");
671 package PMG
::API2
::Nodes
;
676 use PVE
::RESTHandler
;
677 use PVE
::JSONSchema
qw(get_standard_option);
679 use PMG
::RESTEnvironment
;
681 use base
qw(PVE::RESTHandler);
683 __PACKAGE__-
>register_method ({
684 subclass
=> "PMG::API2::NodeInfo",
688 __PACKAGE__-
>register_method ({
692 permissions
=> { user
=> 'all' },
693 description
=> "Cluster node index.",
695 additionalProperties
=> 0,
704 links
=> [ { rel
=> 'child', href
=> "{node}" } ],
709 my $nodename = PVE
::INotify
::nodename
();
711 my $res = [ { node
=> $nodename } ];
715 $done->{$nodename} = 1;
717 my $restenv = PMG
::RESTEnvironment-
>get();
718 my $cinfo = $restenv->{cinfo
};
720 foreach my $ni (values %{$cinfo->{ids
}}) {
721 push @$res, { node
=> $ni->{name
} } if !$done->{$ni->{name
}};
722 $done->{$ni->{name
}} = 1;