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