]>
Commit | Line | Data |
---|---|---|
3813e7b4 DM |
1 | package PVE::API2Tools; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
8208f7db DM |
5 | use Net::IP; |
6 | ||
fdb3516b | 7 | use PVE::Exception qw(raise_param_exc); |
dab54677 | 8 | use PVE::Tools; |
0f5bc844 | 9 | use PVE::INotify; |
fdb3516b | 10 | use PVE::Cluster; |
a029c045 | 11 | use PVE::DataCenterConfig; |
d5394704 | 12 | use PVE::RPCEnvironment; |
dab54677 | 13 | use Digest::MD5 qw(md5_hex); |
12f6913e DM |
14 | use URI; |
15 | use URI::Escape; | |
ce1626a7 | 16 | use PVE::SafeSyslog; |
903e8ace | 17 | use PVE::Storage::Plugin; |
dab54677 DM |
18 | |
19 | my $hwaddress; | |
20 | ||
21 | sub get_hwaddress { | |
29d61517 | 22 | |
dab54677 DM |
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 | } | |
3813e7b4 | 31 | |
d100ceaa | 32 | sub extract_node_stats { |
932b3930 | 33 | my ($node, $members, $rrd, $exclude_stats) = @_; |
d100ceaa DM |
34 | |
35 | my $entry = { | |
36 | id => "node/$node", | |
37 | node => $node, | |
38 | type => "node", | |
71440a94 | 39 | status => 'unknown', |
d100ceaa DM |
40 | }; |
41 | ||
42 | if (my $d = $rrd->{"pve2-node/$node"}) { | |
932b3930 | 43 | |
d100ceaa DM |
44 | if (!$members || # no cluster |
45 | ($members->{$node} && $members->{$node}->{online})) { | |
932b3930 TL |
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 | } | |
71440a94 | 52 | $entry->{status} = 'online'; |
d100ceaa DM |
53 | } |
54 | $entry->{level} = $d->[1]; | |
932b3930 TL |
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 | } | |
d100ceaa DM |
60 | } |
61 | ||
71440a94 DC |
62 | if ($members && $members->{$node} && |
63 | !$members->{$node}->{online}) { | |
64 | $entry->{status} = 'offline'; | |
65 | } | |
66 | ||
d100ceaa DM |
67 | return $entry; |
68 | } | |
3813e7b4 DM |
69 | |
70 | sub extract_vm_stats { | |
71 | my ($vmid, $data, $rrd) = @_; | |
72 | ||
73 | my $entry = { | |
74 | id => "$data->{type}/$vmid", | |
29d61517 | 75 | vmid => $vmid + 0, |
3813e7b4 DM |
76 | node => $data->{node}, |
77 | type => $data->{type}, | |
ae2bf812 | 78 | status => 'unknown', |
3813e7b4 DM |
79 | }; |
80 | ||
a34da77e DM |
81 | my $d; |
82 | ||
83 | if ($d = $rrd->{"pve2-vm/$vmid"}) { | |
3813e7b4 DM |
84 | |
85 | $entry->{uptime} = ($d->[0] || 0) + 0; | |
86 | $entry->{name} = $d->[1]; | |
decdf011 | 87 | $entry->{status} = $entry->{uptime} ? 'running' : 'stopped'; |
3813e7b4 DM |
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; | |
be112d89 AD |
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; | |
29d61517 | 98 | |
a34da77e | 99 | } elsif ($d = $rrd->{"pve2.3-vm/$vmid"}) { |
decdf011 DM |
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; | |
3813e7b4 DM |
116 | }; |
117 | ||
118 | return $entry; | |
bbac9373 | 119 | } |
3813e7b4 DM |
120 | |
121 | sub extract_storage_stats { | |
122 | my ($storeid, $scfg, $node, $rrd) = @_; | |
123 | ||
903e8ace FE |
124 | my $content = PVE::Storage::Plugin::content_hash_to_string($scfg->{content}); |
125 | ||
3813e7b4 DM |
126 | my $entry = { |
127 | id => "storage/$node/$storeid", | |
29d61517 TM |
128 | storage => $storeid, |
129 | node => $node, | |
130 | type => 'storage', | |
e30fdf0a | 131 | plugintype => $scfg->{type}, |
26f6f09c | 132 | status => 'unknown', |
e46f232c | 133 | shared => $scfg->{shared} || 0, |
903e8ace | 134 | content => $content, |
29d61517 | 135 | }; |
3813e7b4 DM |
136 | |
137 | if (my $d = $rrd->{"pve2-storage/$node/$storeid"}) { | |
138 | $entry->{maxdisk} = ($d->[1] || 0) + 0; | |
139 | $entry->{disk} = ($d->[2] || 0) + 0; | |
26f6f09c | 140 | $entry->{status} = 'available'; |
3813e7b4 DM |
141 | } |
142 | ||
143 | return $entry; | |
bbac9373 | 144 | } |
3813e7b4 | 145 | |
12f6913e DM |
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 | ||
ce1626a7 DM |
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(); | |
ce1626a7 | 170 | |
0f5bc844 WB |
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); | |
29d61517 TM |
174 | |
175 | my ($ticket, undef, $remote_viewer_config) = | |
a690f58c | 176 | PVE::AccessControl::remote_viewer_config($authuser, $vmid, $node, $proxy, $title, $port); |
ce1626a7 | 177 | |
29d61517 | 178 | my $timeout = 40; |
ce1626a7 | 179 | |
b3f1c7e9 | 180 | my $cmd = ['/usr/bin/spiceterm', '--port', $port, '--addr', 'localhost', |
29d61517 | 181 | '--timeout', $timeout, '--authpath', $authpath, |
ce1626a7 DM |
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 | ||
343a8dff | 197 | eval { |
ce1626a7 | 198 | foreach my $k (keys %ENV) { |
343a8dff | 199 | next if $k eq 'PATH' || $k eq 'TERM' || $k eq 'USER' || $k eq 'HOME' || $k eq 'LANG' || $k eq 'LANGUAGE' ; |
ce1626a7 DM |
200 | delete $ENV{$k}; |
201 | } | |
202 | $ENV{PWD} = '/'; | |
203 | $ENV{SPICE_TICKET} = $ticket; | |
343a8dff | 204 | |
ef4c3b75 | 205 | PVE::Tools::run_command($cmd, errmsg => 'spiceterm failed\n', keeplocale => 1); |
ce1626a7 DM |
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 | } | |
a690f58c | 219 | |
ce1626a7 DM |
220 | PVE::Tools::wait_for_vnc_port($port); |
221 | ||
a690f58c | 222 | return $remote_viewer_config; |
ce1626a7 DM |
223 | } |
224 | ||
fdb3516b DM |
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}; | |
ce12a5a7 | 235 | raise_param_exc({ $proxyto => "proxyto parameter does not exist"}) |
fdb3516b DM |
236 | if !$node; |
237 | } | |
238 | return $node; | |
239 | } | |
240 | ||
16efd355 TM |
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 | ||
d5394704 | 251 | die "pool '$pool' does not exist\n" if !$data; |
16efd355 | 252 | |
d5394704 | 253 | my $pool_members = [ grep { $idlist->{$_} } keys %{$data->{vms}} ]; |
16efd355 | 254 | |
d5394704 | 255 | return $pool_members; |
16efd355 TM |
256 | } |
257 | ||
3813e7b4 | 258 | 1; |