]>
git.proxmox.com Git - pmg-api.git/blob - PMG/API2/Nodes.pm
0f913b9f0ae627369dd39a319d6a10f21bbd6655
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
::Postfix
;
25 use PMG
::API2
::MailTracker
;
27 use base
qw(PVE::RESTHandler);
29 __PACKAGE__-
>register_method ({
30 subclass
=> "PMG::API2::Postfix",
34 __PACKAGE__-
>register_method ({
35 subclass
=> "PMG::API2::ClamAV",
39 __PACKAGE__-
>register_method ({
40 subclass
=> "PMG::API2::Network",
44 __PACKAGE__-
>register_method ({
45 subclass
=> "PMG::API2::Tasks",
49 __PACKAGE__-
>register_method ({
50 subclass
=> "PMG::API2::Services",
54 __PACKAGE__-
>register_method ({
55 subclass
=> "PMG::API2::Subscription",
56 path
=> 'subscription',
59 __PACKAGE__-
>register_method ({
60 subclass
=> "PMG::API2::APT",
64 __PACKAGE__-
>register_method ({
65 subclass
=> "PMG::API2::MailTracker",
69 __PACKAGE__-
>register_method ({
73 permissions
=> { user
=> 'all' },
74 description
=> "Node index.",
76 additionalProperties
=> 0,
78 node
=> get_standard_option
('pve-node'),
87 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
95 { name
=> 'postfix' },
96 { name
=> 'services' },
99 { name
=> 'tracker' },
101 { name
=> 'status' },
102 { name
=> 'subscription' },
103 { name
=> 'vncshell' },
104 { name
=> 'rrddata' },
110 __PACKAGE__-
>register_method({
114 protected
=> 1, # fixme: can we avoid that?
116 permissions
=> { check
=> [ 'admin', 'audit' ] },
117 description
=> "Read node RRD statistics",
119 additionalProperties
=> 0,
121 node
=> get_standard_option
('pve-node'),
123 description
=> "Specify the time frame you are interested in.",
125 enum
=> [ 'hour', 'day', 'week', 'month', 'year' ],
128 description
=> "The RRD consolidation function",
130 enum
=> [ 'AVERAGE', 'MAX' ],
145 return PMG
::Utils
::create_rrd_data
(
146 "pmg-node-v1.rrd", $param->{timeframe
}, $param->{cf
});
150 __PACKAGE__-
>register_method({
154 description
=> "Read system log",
157 permissions
=> { check
=> [ 'admin', 'audit' ] },
159 additionalProperties
=> 0,
161 node
=> get_standard_option
('pve-node'),
174 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
175 description
=> "Display all log since this date-time string.",
180 pattern
=> '^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$',
181 description
=> "Display all log until this date-time string.",
185 description
=> "Service ID",
198 description
=> "Line number",
202 description
=> "Line text",
211 my $restenv = PMG
::RESTEnvironment-
>get();
213 my $service = $param->{service
};
214 $service = PMG
::Utils
::lookup_real_service_name
($service)
217 my ($count, $lines) = PVE
::Tools
::dump_journal
(
218 $param->{start
}, $param->{limit
},
219 $param->{since
}, $param->{'until'}, $service);
221 $restenv->set_result_attrib('total', $count);
226 __PACKAGE__-
>register_method ({
231 description
=> "Creates a VNC Shell proxy.",
233 additionalProperties
=> 0,
235 node
=> get_standard_option
('pve-node'),
238 description
=> "Run 'apt-get dist-upgrade' instead of normal shell.",
245 description
=> "use websocket instead of standard vnc.",
251 additionalProperties
=> 0,
253 user
=> { type
=> 'string' },
254 ticket
=> { type
=> 'string' },
255 port
=> { type
=> 'integer' },
256 upid
=> { type
=> 'string' },
262 my $node = $param->{node
};
264 if ($node ne PVE
::INotify
::nodename
()) {
265 die "vncproxy to remote node not implemented";
268 # we only implement the websocket based VNC here
269 my $websocket = $param->{websocket
} // 1;
270 die "standard VNC not implemented" if !$websocket;
272 my $authpath = "/nodes/$node";
274 my $restenv = PMG
::RESTEnvironment-
>get();
275 my $user = $restenv->get_user();
277 raise_perm_exc
('user != root@pam') if $param->{upgrade
} && $user ne 'root@pam';
279 my $ticket = PMG
::Ticket
::assemble_vnc_ticket
($user, $authpath);
281 my $family = PVE
::Tools
::get_host_address_family
($node);
282 my $port = PVE
::Tools
::next_vnc_port
($family);
286 if ($user eq 'root@pam') {
287 if ($param->{upgrade
}) {
288 my $upgradecmd = "pmgupgrade --shell";
289 # $upgradecmd = PVE::Tools::shellquote($upgradecmd) if $remip;
290 $shcmd = [ '/bin/bash', '-c', $upgradecmd ];
292 $shcmd = [ '/bin/login', '-f', 'root' ];
295 $shcmd = [ '/bin/login' ];
298 my $cmd = ['/usr/bin/vncterm', '-rfbport', $port,
299 '-timeout', 10, '-notls', '-listen', 'localhost',
305 syslog
('info', "starting vnc proxy $upid\n");
307 my $cmdstr = join (' ', @$cmd);
308 syslog
('info', "launch command: $cmdstr");
311 foreach my $k (keys %ENV) {
312 next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME';
317 $ENV{PVE_VNC_TICKET
} = $ticket; # pass ticket to vncterm
319 PVE
::Tools
::run_command
($cmd, errmsg
=> "vncterm failed");
328 my $upid = $restenv->fork_worker('vncshell', "", $user, $realcmd);
330 PVE
::Tools
::wait_for_vnc_port
($port);
340 __PACKAGE__-
>register_method({
341 name
=> 'vncwebsocket',
342 path
=> 'vncwebsocket',
344 description
=> "Opens a weksocket for VNC traffic.",
346 additionalProperties
=> 0,
348 node
=> get_standard_option
('pve-node'),
350 description
=> "Ticket from previous call to vncproxy.",
355 description
=> "Port number returned by previous vncproxy call.",
365 port
=> { type
=> 'string' },
371 my $authpath = "/nodes/$param->{node}";
373 my $restenv = PMG
::RESTEnvironment-
>get();
374 my $user = $restenv->get_user();
376 PMG
::Ticket
::verify_vnc_ticket
($param->{vncticket
}, $user, $authpath);
378 my $port = $param->{port
};
380 return { port
=> $port };
383 __PACKAGE__-
>register_method({
387 description
=> "Read DNS settings.",
390 additionalProperties
=> 0,
392 node
=> get_standard_option
('pve-node'),
397 additionalProperties
=> 0,
400 description
=> "Search domain for host-name lookup.",
405 description
=> 'First name server IP address.',
410 description
=> 'Second name server IP address.',
415 description
=> 'Third name server IP address.',
424 my $res = PVE
::INotify
::read_file
('resolvconf');
429 __PACKAGE__-
>register_method({
430 name
=> 'update_dns',
433 description
=> "Write DNS settings.",
437 additionalProperties
=> 0,
439 node
=> get_standard_option
('pve-node'),
441 description
=> "Search domain for host-name lookup.",
445 description
=> 'First name server IP address.',
446 type
=> 'string', format
=> 'ip',
450 description
=> 'Second name server IP address.',
451 type
=> 'string', format
=> 'ip',
455 description
=> 'Third name server IP address.',
456 type
=> 'string', format
=> 'ip',
461 returns
=> { type
=> "null" },
465 PVE
::INotify
::update_file
('resolvconf', $param);
471 __PACKAGE__-
>register_method({
475 description
=> "Read server time and time zone settings.",
478 additionalProperties
=> 0,
480 node
=> get_standard_option
('pve-node'),
485 additionalProperties
=> 0,
488 description
=> "Time zone",
492 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
494 minimum
=> 1297163644,
497 description
=> "Seconds since 1970-01-01 00:00:00 (local time)",
499 minimum
=> 1297163644,
507 my $ltime = timegm_nocheck
(localtime($ctime));
509 timezone
=> PVE
::INotify
::read_file
('timezone'),
517 __PACKAGE__-
>register_method({
518 name
=> 'set_timezone',
521 description
=> "Set time zone.",
525 additionalProperties
=> 0,
527 node
=> get_standard_option
('pve-node'),
529 description
=> "Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.",
534 returns
=> { type
=> "null" },
538 PVE
::INotify
::write_file
('timezone', $param->{timezone
});
543 __PACKAGE__-
>register_method({
547 description
=> "Read server status. This is used by the cluster manager to test the node health.",
551 additionalProperties
=> 0,
553 node
=> get_standard_option
('pve-node'),
558 additionalProperties
=> 1,
561 description
=> "Seconds since 1970-01-01 00:00:00 UTC.",
563 minimum
=> 1297163644,
566 description
=> "The uptime of the system in seconds.",
571 description
=> "Database is synced with other nodes.",
579 my $restenv = PMG
::RESTEnvironment-
>get();
580 my $cinfo = $restenv->{cinfo
};
584 my $res = { time => $ctime, insync
=> 1 };
586 my $si = PMG
::DBTools
::cluster_sync_status
($cinfo);
587 foreach my $cid (keys %$si) {
588 my $lastsync = $si->{$cid};
589 my $sdiff = $ctime - $lastsync;
590 $sdiff = 0 if $sdiff < 0;
591 $res->{insync
} = 0 if $sdiff > (60*3);
594 my ($uptime, $idle) = PVE
::ProcFSTools
::read_proc_uptime
();
595 $res->{uptime
} = $uptime;
597 my ($avg1, $avg5, $avg15) = PVE
::ProcFSTools
::read_loadavg
();
598 $res->{loadavg
} = [ $avg1, $avg5, $avg15];
600 my ($sysname, $nodename, $release, $version, $machine) = POSIX
::uname
();
602 $res->{kversion
} = "$sysname $release $version";
604 $res->{cpuinfo
} = PVE
::ProcFSTools
::read_cpuinfo
();
606 my $stat = PVE
::ProcFSTools
::read_proc_stat
();
607 $res->{cpu
} = $stat->{cpu
};
608 $res->{wait} = $stat->{wait};
610 my $meminfo = PVE
::ProcFSTools
::read_meminfo
();
612 free
=> $meminfo->{memfree
},
613 total
=> $meminfo->{memtotal
},
614 used
=> $meminfo->{memused
},
618 free
=> $meminfo->{swapfree
},
619 total
=> $meminfo->{swaptotal
},
620 used
=> $meminfo->{swapused
},
623 $res->{pmgversion
} = PMG
::pmgcfg
::package() . "/" .
624 PMG
::pmgcfg
::version_text
();
626 my $dinfo = df
('/', 1); # output is bytes
629 total
=> $dinfo->{blocks
},
630 avail
=> $dinfo->{bavail
},
631 used
=> $dinfo->{used
},
632 free
=> $dinfo->{bavail
} - $dinfo->{used
},
635 if (my $subinfo = PVE
::INotify
::read_file
('subscription')) {
636 if (my $level = $subinfo->{level
}) {
637 $res->{level
} = $level;
645 package PMG
::API2
::Nodes
;
650 use PVE
::RESTHandler
;
651 use PVE
::JSONSchema
qw(get_standard_option);
653 use PMG
::RESTEnvironment
;
655 use base
qw(PVE::RESTHandler);
657 __PACKAGE__-
>register_method ({
658 subclass
=> "PMG::API2::NodeInfo",
662 __PACKAGE__-
>register_method ({
666 permissions
=> { user
=> 'all' },
667 description
=> "Cluster node index.",
669 additionalProperties
=> 0,
678 links
=> [ { rel
=> 'child', href
=> "{node}" } ],
683 my $nodename = PVE
::INotify
::nodename
();
685 my $res = [ { node
=> $nodename } ];
689 $done->{$nodename} = 1;
691 my $restenv = PMG
::RESTEnvironment-
>get();
692 my $cinfo = $restenv->{cinfo
};
694 foreach my $ni (values %{$cinfo->{ids
}}) {
695 push @$res, { node
=> $ni->{name
} } if !$done->{$ni->{name
}};
696 $done->{$ni->{name
}} = 1;