1 package PVE
::API2Tools
;
6 use Digest
::MD5
qw(md5_hex);
13 use PVE
::DataCenterConfig
; # so we can cfs-read datacenter.cfg
14 use PVE
::Exception
qw(raise_param_exc);
16 use PVE
::RPCEnvironment
;
18 use PVE
::Storage
::Plugin
;
22 my $hwaddress_st = {};
25 my $fn = '/etc/ssh/ssh_host_rsa_key.pub';
28 if (defined($hwaddress)
29 && $hwaddress_st->{mtime
} == $st->mtime
30 && $hwaddress_st->{ino
} == $st->ino
31 && $hwaddress_st->{dev
} == $st->dev) {
35 my $sshkey = PVE
::Tools
::file_get_contents
($fn);
36 $hwaddress = uc(md5_hex
($sshkey));
37 $hwaddress_st->@{'mtime', 'ino', 'dev'} = ($st->mtime, $st->ino, $st->dev);
42 sub extract_node_stats
{
43 my ($node, $members, $rrd, $exclude_stats) = @_;
52 if (my $d = $rrd->{"pve2-node/$node"}) {
54 if (!$members || # no cluster
55 ($members->{$node} && $members->{$node}->{online
})) {
56 if (!$exclude_stats) {
57 $entry->{uptime
} = ($d->[0] || 0) + 0;
58 $entry->{cpu
} = ($d->[5] || 0) + 0;
59 $entry->{mem
} = ($d->[8] || 0) + 0;
60 $entry->{disk
} = ($d->[12] || 0) + 0;
62 $entry->{status
} = 'online';
64 $entry->{level
} = $d->[1];
65 if (!$exclude_stats) {
66 $entry->{maxcpu
} = ($d->[4] || 0) + 0;
67 $entry->{maxmem
} = ($d->[7] || 0) + 0;
68 $entry->{maxdisk
} = ($d->[11] || 0) + 0;
72 if ($members && $members->{$node} &&
73 !$members->{$node}->{online
}) {
74 $entry->{status
} = 'offline';
80 sub extract_vm_stats
{
81 my ($vmid, $data, $rrd) = @_;
84 id
=> "$data->{type}/$vmid",
86 node
=> $data->{node
},
87 type
=> $data->{type
},
93 if ($d = $rrd->{"pve2-vm/$vmid"}) {
95 $entry->{uptime
} = ($d->[0] || 0) + 0;
96 $entry->{name
} = $d->[1];
97 $entry->{status
} = $entry->{uptime
} ?
'running' : 'stopped';
98 $entry->{maxcpu
} = ($d->[3] || 0) + 0;
99 $entry->{cpu
} = ($d->[4] || 0) + 0;
100 $entry->{maxmem
} = ($d->[5] || 0) + 0;
101 $entry->{mem
} = ($d->[6] || 0) + 0;
102 $entry->{maxdisk
} = ($d->[7] || 0) + 0;
103 $entry->{disk
} = ($d->[8] || 0) + 0;
104 $entry->{netin
} = ($d->[9] || 0) + 0;
105 $entry->{netout
} = ($d->[10] || 0) + 0;
106 $entry->{diskread
} = ($d->[11] || 0) + 0;
107 $entry->{diskwrite
} = ($d->[12] || 0) + 0;
109 } elsif ($d = $rrd->{"pve2.3-vm/$vmid"}) {
111 $entry->{uptime
} = ($d->[0] || 0) + 0;
112 $entry->{name
} = $d->[1];
113 $entry->{status
} = $d->[2];
114 $entry->{template
} = $d->[3] + 0;
116 $entry->{maxcpu
} = ($d->[5] || 0) + 0;
117 $entry->{cpu
} = ($d->[6] || 0) + 0;
118 $entry->{maxmem
} = ($d->[7] || 0) + 0;
119 $entry->{mem
} = ($d->[8] || 0) + 0;
120 $entry->{maxdisk
} = ($d->[9] || 0) + 0;
121 $entry->{disk
} = ($d->[10] || 0) + 0;
122 $entry->{netin
} = ($d->[11] || 0) + 0;
123 $entry->{netout
} = ($d->[12] || 0) + 0;
124 $entry->{diskread
} = ($d->[13] || 0) + 0;
125 $entry->{diskwrite
} = ($d->[14] || 0) + 0;
131 sub extract_storage_stats
{
132 my ($storeid, $scfg, $node, $rrd) = @_;
134 my $content = PVE
::Storage
::Plugin
::content_hash_to_string
($scfg->{content
});
137 id
=> "storage/$node/$storeid",
141 plugintype
=> $scfg->{type
},
143 shared
=> $scfg->{shared
} || 0,
147 if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) {
148 $entry->{maxdisk
} = ($d->[1] || 0) + 0;
149 $entry->{disk
} = ($d->[2] || 0) + 0;
150 $entry->{status
} = 'available';
156 sub parse_http_proxy
{
159 my $uri = URI-
>new($proxyenv);
161 my $scheme = $uri->scheme;
162 my $host = $uri->host;
163 my $port = $uri->port || 3128;
165 my ($username, $password);
167 if (defined(my $p_auth = $uri->userinfo())) {
168 ($username, $password) = map URI
::Escape
::uri_unescape
($_), split(":", $p_auth, 2);
171 return ("$host:$port", $username, $password);
175 my ($authpath, $permissions, $vmid, $node, $proxy, $title, $shcmd) = @_;
177 my $rpcenv = PVE
::RPCEnvironment
::get
();
179 my $authuser = $rpcenv->get_user();
181 my $nodename = PVE
::INotify
::nodename
();
182 my $family = PVE
::Tools
::get_host_address_family
($nodename);
183 my $port = PVE
::Tools
::next_spice_port
($family);
185 my ($ticket, undef, $remote_viewer_config) =
186 PVE
::AccessControl
::remote_viewer_config
($authuser, $vmid, $node, $proxy, $title, $port);
190 my $cmd = ['/usr/bin/spiceterm', '--port', $port, '--addr', 'localhost',
191 '--timeout', $timeout, '--authpath', $authpath,
192 '--permissions', $permissions];
194 my $dcconf = PVE
::Cluster
::cfs_read_file
('datacenter.cfg');
195 push @$cmd, '--keymap', $dcconf->{keyboard
} if $dcconf->{keyboard
};
197 push @$cmd, '--', @$shcmd;
202 syslog
('info', "starting spiceterm $upid - $title\n");
204 my $cmdstr = join (' ', @$cmd);
205 syslog
('info', "launch command: $cmdstr");
208 foreach my $k (keys %ENV) {
209 next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME' || $k eq 'LANG' || $k eq 'LANGUAGE' ;
213 $ENV{SPICE_TICKET
} = $ticket;
215 PVE
::Tools
::run_command
($cmd, errmsg
=> 'spiceterm failed\n', keeplocale
=> 1);
218 syslog
('err', $err);
225 $rpcenv->fork_worker('spiceproxy', $vmid, $authuser, $realcmd);
227 $rpcenv->fork_worker('spiceshell', undef, $authuser, $realcmd);
230 PVE
::Tools
::wait_for_vnc_port
($port);
232 return $remote_viewer_config;
235 sub resolve_proxyto
{
236 my ($rpcenv, $proxyto_callback, $proxyto, $uri_param) = @_;
239 if ($proxyto_callback) {
240 $node = $proxyto_callback->($rpcenv, $proxyto, $uri_param);
241 die "internal error - proxyto_callback returned nothing\n"
244 $node = $uri_param->{$proxyto};
245 raise_param_exc
({ $proxyto => "proxyto parameter does not exist"})
251 sub get_resource_pool_guest_members
{
254 my $usercfg = PVE
::Cluster
::cfs_read_file
("user.cfg");
256 my $vmlist = PVE
::Cluster
::get_vmlist
() || {};
257 my $idlist = $vmlist->{ids
} || {};
259 my $data = $usercfg->{pools
}->{$pool};
261 die "pool '$pool' does not exist\n" if !$data;
263 my $pool_members = [ grep { $idlist->{$_} } keys %{$data->{vms
}} ];
265 return $pool_members;