]> git.proxmox.com Git - pve-manager.git/blob - PVE/API2Tools.pm
ui: utils: monitor_ceph_installed: avoid setting nodename to localhost
[pve-manager.git] / PVE / API2Tools.pm
1 package PVE::API2Tools;
2
3 use strict;
4 use warnings;
5 use Net::IP;
6
7 use PVE::Exception qw(raise_param_exc);
8 use PVE::Tools;
9 use PVE::INotify;
10 use PVE::Cluster;
11 use PVE::DataCenterConfig;
12 use PVE::RPCEnvironment;
13 use Digest::MD5 qw(md5_hex);
14 use URI;
15 use URI::Escape;
16 use PVE::SafeSyslog;
17 use PVE::Storage::Plugin;
18
19 my $hwaddress;
20
21 sub get_hwaddress {
22
23 return $hwaddress if defined ($hwaddress);
24
25 my $fn = '/etc/ssh/ssh_host_rsa_key.pub';
26 my $sshkey = PVE::Tools::file_get_contents($fn);
27 $hwaddress = uc(md5_hex($sshkey));
28
29 return $hwaddress;
30 }
31
32 sub extract_node_stats {
33 my ($node, $members, $rrd, $exclude_stats) = @_;
34
35 my $entry = {
36 id => "node/$node",
37 node => $node,
38 type => "node",
39 status => 'unknown',
40 };
41
42 if (my $d = $rrd->{"pve2-node/$node"}) {
43
44 if (!$members || # no cluster
45 ($members->{$node} && $members->{$node}->{online})) {
46 if (!$exclude_stats) {
47 $entry->{uptime} = ($d->[0] || 0) + 0;
48 $entry->{cpu} = ($d->[5] || 0) + 0;
49 $entry->{mem} = ($d->[8] || 0) + 0;
50 $entry->{disk} = ($d->[12] || 0) + 0;
51 }
52 $entry->{status} = 'online';
53 }
54 $entry->{level} = $d->[1];
55 if (!$exclude_stats) {
56 $entry->{maxcpu} = ($d->[4] || 0) + 0;
57 $entry->{maxmem} = ($d->[7] || 0) + 0;
58 $entry->{maxdisk} = ($d->[11] || 0) + 0;
59 }
60 }
61
62 if ($members && $members->{$node} &&
63 !$members->{$node}->{online}) {
64 $entry->{status} = 'offline';
65 }
66
67 return $entry;
68 }
69
70 sub extract_vm_stats {
71 my ($vmid, $data, $rrd) = @_;
72
73 my $entry = {
74 id => "$data->{type}/$vmid",
75 vmid => $vmid + 0,
76 node => $data->{node},
77 type => $data->{type},
78 status => 'unknown',
79 };
80
81 my $d;
82
83 if ($d = $rrd->{"pve2-vm/$vmid"}) {
84
85 $entry->{uptime} = ($d->[0] || 0) + 0;
86 $entry->{name} = $d->[1];
87 $entry->{status} = $entry->{uptime} ? 'running' : 'stopped';
88 $entry->{maxcpu} = ($d->[3] || 0) + 0;
89 $entry->{cpu} = ($d->[4] || 0) + 0;
90 $entry->{maxmem} = ($d->[5] || 0) + 0;
91 $entry->{mem} = ($d->[6] || 0) + 0;
92 $entry->{maxdisk} = ($d->[7] || 0) + 0;
93 $entry->{disk} = ($d->[8] || 0) + 0;
94 $entry->{netin} = ($d->[9] || 0) + 0;
95 $entry->{netout} = ($d->[10] || 0) + 0;
96 $entry->{diskread} = ($d->[11] || 0) + 0;
97 $entry->{diskwrite} = ($d->[12] || 0) + 0;
98
99 } elsif ($d = $rrd->{"pve2.3-vm/$vmid"}) {
100
101 $entry->{uptime} = ($d->[0] || 0) + 0;
102 $entry->{name} = $d->[1];
103 $entry->{status} = $d->[2];
104 $entry->{template} = $d->[3] + 0;
105
106 $entry->{maxcpu} = ($d->[5] || 0) + 0;
107 $entry->{cpu} = ($d->[6] || 0) + 0;
108 $entry->{maxmem} = ($d->[7] || 0) + 0;
109 $entry->{mem} = ($d->[8] || 0) + 0;
110 $entry->{maxdisk} = ($d->[9] || 0) + 0;
111 $entry->{disk} = ($d->[10] || 0) + 0;
112 $entry->{netin} = ($d->[11] || 0) + 0;
113 $entry->{netout} = ($d->[12] || 0) + 0;
114 $entry->{diskread} = ($d->[13] || 0) + 0;
115 $entry->{diskwrite} = ($d->[14] || 0) + 0;
116 };
117
118 return $entry;
119 }
120
121 sub extract_storage_stats {
122 my ($storeid, $scfg, $node, $rrd) = @_;
123
124 my $content = PVE::Storage::Plugin::content_hash_to_string($scfg->{content});
125
126 my $entry = {
127 id => "storage/$node/$storeid",
128 storage => $storeid,
129 node => $node,
130 type => 'storage',
131 plugintype => $scfg->{type},
132 status => 'unknown',
133 shared => $scfg->{shared} || 0,
134 content => $content,
135 };
136
137 if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) {
138 $entry->{maxdisk} = ($d->[1] || 0) + 0;
139 $entry->{disk} = ($d->[2] || 0) + 0;
140 $entry->{status} = 'available';
141 }
142
143 return $entry;
144 }
145
146 sub parse_http_proxy {
147 my ($proxyenv) = @_;
148
149 my $uri = URI->new($proxyenv);
150
151 my $scheme = $uri->scheme;
152 my $host = $uri->host;
153 my $port = $uri->port || 3128;
154
155 my ($username, $password);
156
157 if (defined(my $p_auth = $uri->userinfo())) {
158 ($username, $password) = map URI::Escape::uri_unescape($_), split(":", $p_auth, 2);
159 }
160
161 return ("$host:$port", $username, $password);
162 }
163
164 sub run_spiceterm {
165 my ($authpath, $permissions, $vmid, $node, $proxy, $title, $shcmd) = @_;
166
167 my $rpcenv = PVE::RPCEnvironment::get();
168
169 my $authuser = $rpcenv->get_user();
170
171 my $nodename = PVE::INotify::nodename();
172 my $family = PVE::Tools::get_host_address_family($nodename);
173 my $port = PVE::Tools::next_spice_port($family);
174
175 my ($ticket, undef, $remote_viewer_config) =
176 PVE::AccessControl::remote_viewer_config($authuser, $vmid, $node, $proxy, $title, $port);
177
178 my $timeout = 40;
179
180 my $cmd = ['/usr/bin/spiceterm', '--port', $port, '--addr', 'localhost',
181 '--timeout', $timeout, '--authpath', $authpath,
182 '--permissions', $permissions];
183
184 my $dcconf = PVE::Cluster::cfs_read_file('datacenter.cfg');
185 push @$cmd, '--keymap', $dcconf->{keyboard} if $dcconf->{keyboard};
186
187 push @$cmd, '--', @$shcmd;
188
189 my $realcmd = sub {
190 my $upid = shift;
191
192 syslog ('info', "starting spiceterm $upid - $title\n");
193
194 my $cmdstr = join (' ', @$cmd);
195 syslog ('info', "launch command: $cmdstr");
196
197 eval {
198 foreach my $k (keys %ENV) {
199 next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME' || $k eq 'LANG' || $k eq 'LANGUAGE' ;
200 delete $ENV{$k};
201 }
202 $ENV{PWD} = '/';
203 $ENV{SPICE_TICKET} = $ticket;
204
205 PVE::Tools::run_command($cmd, errmsg => 'spiceterm failed\n', keeplocale => 1);
206 };
207 if (my $err = $@) {
208 syslog ('err', $err);
209 }
210
211 return;
212 };
213
214 if ($vmid) {
215 $rpcenv->fork_worker('spiceproxy', $vmid, $authuser, $realcmd);
216 } else {
217 $rpcenv->fork_worker('spiceshell', undef, $authuser, $realcmd);
218 }
219
220 PVE::Tools::wait_for_vnc_port($port);
221
222 return $remote_viewer_config;
223 }
224
225 sub resolve_proxyto {
226 my ($rpcenv, $proxyto_callback, $proxyto, $uri_param) = @_;
227
228 my $node;
229 if ($proxyto_callback) {
230 $node = $proxyto_callback->($rpcenv, $proxyto, $uri_param);
231 die "internal error - proxyto_callback returned nothing\n"
232 if !$node;
233 } else {
234 $node = $uri_param->{$proxyto};
235 raise_param_exc({ $proxyto => "proxyto parameter does not exist"})
236 if !$node;
237 }
238 return $node;
239 }
240
241 sub get_resource_pool_guest_members {
242 my ($pool) = @_;
243
244 my $usercfg = PVE::Cluster::cfs_read_file("user.cfg");
245
246 my $vmlist = PVE::Cluster::get_vmlist() || {};
247 my $idlist = $vmlist->{ids} || {};
248
249 my $data = $usercfg->{pools}->{$pool};
250
251 die "pool '$pool' does not exist\n" if !$data;
252
253 my $pool_members = [ grep { $idlist->{$_} } keys %{$data->{vms}} ];
254
255 return $pool_members;
256 }
257
258 1;