]> git.proxmox.com Git - pve-manager.git/blame - PVE/API2Tools.pm
update shipped appliance info index
[pve-manager.git] / PVE / API2Tools.pm
CommitLineData
19a6b9f1
DM
1package PVE::API2Tools;
2
3use strict;
4use warnings;
e02db471
TL
5
6use Digest::MD5 qw(md5_hex);
fddf562b 7use File::stat;
a3eff2d9 8use Net::IP;
e02db471
TL
9use URI::Escape;
10use URI;
a3eff2d9 11
e02db471
TL
12use PVE::Cluster;
13use PVE::DataCenterConfig; # so we can cfs-read datacenter.cfg
3c54bc91 14use PVE::Exception qw(raise_param_exc);
eb6d7497 15use PVE::INotify;
5ab9a243 16use PVE::RPCEnvironment;
b289829f 17use PVE::SafeSyslog;
74c8984d 18use PVE::Storage::Plugin;
e02db471 19use PVE::Tools;
2ba6d822
DM
20
21my $hwaddress;
f6395eb6 22my $hwaddress_st = {};
2ba6d822
DM
23
24sub get_hwaddress {
f6395eb6
MS
25 my $fn = '/etc/ssh/ssh_host_rsa_key.pub';
26 my $st = stat($fn);
60e049c2 27
f6395eb6
MS
28 if (defined($hwaddress)
29 && $hwaddress_st->{mtime} == $st->mtime
30 && $hwaddress_st->{ino} == $st->ino
31 && $hwaddress_st->{dev} == $st->dev) {
32 return $hwaddress;
33 }
2ba6d822 34
2ba6d822
DM
35 my $sshkey = PVE::Tools::file_get_contents($fn);
36 $hwaddress = uc(md5_hex($sshkey));
f6395eb6 37 $hwaddress_st->@{'mtime', 'ino', 'dev'} = ($st->mtime, $st->ino, $st->dev);
2ba6d822
DM
38
39 return $hwaddress;
40}
19a6b9f1 41
16b69b6c 42sub extract_node_stats {
57d56896 43 my ($node, $members, $rrd, $exclude_stats) = @_;
16b69b6c
DM
44
45 my $entry = {
46 id => "node/$node",
47 node => $node,
48 type => "node",
b67e6398 49 status => 'unknown',
16b69b6c
DM
50 };
51
52 if (my $d = $rrd->{"pve2-node/$node"}) {
57d56896 53
16b69b6c
DM
54 if (!$members || # no cluster
55 ($members->{$node} && $members->{$node}->{online})) {
57d56896
TL
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;
61 }
b67e6398 62 $entry->{status} = 'online';
16b69b6c
DM
63 }
64 $entry->{level} = $d->[1];
57d56896
TL
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;
69 }
16b69b6c
DM
70 }
71
b67e6398
DC
72 if ($members && $members->{$node} &&
73 !$members->{$node}->{online}) {
74 $entry->{status} = 'offline';
75 }
76
16b69b6c
DM
77 return $entry;
78}
19a6b9f1
DM
79
80sub extract_vm_stats {
81 my ($vmid, $data, $rrd) = @_;
82
83 my $entry = {
84 id => "$data->{type}/$vmid",
60e049c2 85 vmid => $vmid + 0,
19a6b9f1
DM
86 node => $data->{node},
87 type => $data->{type},
30cdb0ca 88 status => 'unknown',
19a6b9f1
DM
89 };
90
90c3fae4
DM
91 my $d;
92
93 if ($d = $rrd->{"pve2-vm/$vmid"}) {
19a6b9f1
DM
94
95 $entry->{uptime} = ($d->[0] || 0) + 0;
96 $entry->{name} = $d->[1];
3c353ed2 97 $entry->{status} = $entry->{uptime} ? 'running' : 'stopped';
19a6b9f1
DM
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;
cf497f7d
AD
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;
60e049c2 108
90c3fae4 109 } elsif ($d = $rrd->{"pve2.3-vm/$vmid"}) {
3c353ed2
DM
110
111 $entry->{uptime} = ($d->[0] || 0) + 0;
112 $entry->{name} = $d->[1];
113 $entry->{status} = $d->[2];
114 $entry->{template} = $d->[3] + 0;
115
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;
19a6b9f1
DM
126 };
127
128 return $entry;
ff5fcc8a 129}
19a6b9f1
DM
130
131sub extract_storage_stats {
132 my ($storeid, $scfg, $node, $rrd) = @_;
133
74c8984d
FE
134 my $content = PVE::Storage::Plugin::content_hash_to_string($scfg->{content});
135
19a6b9f1
DM
136 my $entry = {
137 id => "storage/$node/$storeid",
60e049c2
TM
138 storage => $storeid,
139 node => $node,
140 type => 'storage',
77a9ce32 141 plugintype => $scfg->{type},
88466808 142 status => 'unknown',
1ce3fa3b 143 shared => $scfg->{shared} || 0,
74c8984d 144 content => $content,
60e049c2 145 };
19a6b9f1
DM
146
147 if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) {
148 $entry->{maxdisk} = ($d->[1] || 0) + 0;
149 $entry->{disk} = ($d->[2] || 0) + 0;
88466808 150 $entry->{status} = 'available';
19a6b9f1
DM
151 }
152
153 return $entry;
ff5fcc8a 154}
19a6b9f1 155
446b9669
DM
156sub parse_http_proxy {
157 my ($proxyenv) = @_;
158
159 my $uri = URI->new($proxyenv);
160
161 my $scheme = $uri->scheme;
162 my $host = $uri->host;
163 my $port = $uri->port || 3128;
164
165 my ($username, $password);
166
167 if (defined(my $p_auth = $uri->userinfo())) {
168 ($username, $password) = map URI::Escape::uri_unescape($_), split(":", $p_auth, 2);
169 }
170
171 return ("$host:$port", $username, $password);
172}
173
b289829f
DM
174sub run_spiceterm {
175 my ($authpath, $permissions, $vmid, $node, $proxy, $title, $shcmd) = @_;
176
177 my $rpcenv = PVE::RPCEnvironment::get();
178
179 my $authuser = $rpcenv->get_user();
b289829f 180
eb6d7497
WB
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);
60e049c2
TM
184
185 my ($ticket, undef, $remote_viewer_config) =
eb7cd2ce 186 PVE::AccessControl::remote_viewer_config($authuser, $vmid, $node, $proxy, $title, $port);
b289829f 187
60e049c2 188 my $timeout = 40;
b289829f 189
c8e4fedd 190 my $cmd = ['/usr/bin/spiceterm', '--port', $port, '--addr', 'localhost',
60e049c2 191 '--timeout', $timeout, '--authpath', $authpath,
b289829f
DM
192 '--permissions', $permissions];
193
194 my $dcconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
195 push @$cmd, '--keymap', $dcconf->{keyboard} if $dcconf->{keyboard};
196
197 push @$cmd, '--', @$shcmd;
198
199 my $realcmd = sub {
200 my $upid = shift;
201
202 syslog ('info', "starting spiceterm $upid - $title\n");
203
204 my $cmdstr = join (' ', @$cmd);
205 syslog ('info', "launch command: $cmdstr");
206
3fa0b222 207 eval {
b289829f 208 foreach my $k (keys %ENV) {
3fa0b222 209 next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME' || $k eq 'LANG' || $k eq 'LANGUAGE' ;
b289829f
DM
210 delete $ENV{$k};
211 }
212 $ENV{PWD} = '/';
213 $ENV{SPICE_TICKET} = $ticket;
3fa0b222 214
b0d4b407 215 PVE::Tools::run_command($cmd, errmsg => 'spiceterm failed\n', keeplocale => 1);
b289829f
DM
216 };
217 if (my $err = $@) {
218 syslog ('err', $err);
219 }
220
221 return;
222 };
223
224 if ($vmid) {
225 $rpcenv->fork_worker('spiceproxy', $vmid, $authuser, $realcmd);
226 } else {
227 $rpcenv->fork_worker('spiceshell', undef, $authuser, $realcmd);
228 }
eb7cd2ce 229
b289829f
DM
230 PVE::Tools::wait_for_vnc_port($port);
231
eb7cd2ce 232 return $remote_viewer_config;
b289829f
DM
233}
234
3c54bc91
DM
235sub resolve_proxyto {
236 my ($rpcenv, $proxyto_callback, $proxyto, $uri_param) = @_;
237
238 my $node;
239 if ($proxyto_callback) {
240 $node = $proxyto_callback->($rpcenv, $proxyto, $uri_param);
241 die "internal error - proxyto_callback returned nothing\n"
242 if !$node;
243 } else {
244 $node = $uri_param->{$proxyto};
a7f04758 245 raise_param_exc({ $proxyto => "proxyto parameter does not exist"})
3c54bc91
DM
246 if !$node;
247 }
248 return $node;
249}
250
f3376261
TM
251sub get_resource_pool_guest_members {
252 my ($pool) = @_;
253
254 my $usercfg = PVE::Cluster::cfs_read_file("user.cfg");
255
256 my $vmlist = PVE::Cluster::get_vmlist() || {};
257 my $idlist = $vmlist->{ids} || {};
258
259 my $data = $usercfg->{pools}->{$pool};
260
5ab9a243 261 die "pool '$pool' does not exist\n" if !$data;
f3376261 262
5ab9a243 263 my $pool_members = [ grep { $idlist->{$_} } keys %{$data->{vms}} ];
f3376261 264
5ab9a243 265 return $pool_members;
f3376261
TM
266}
267
19a6b9f1 2681;