ia64/xen-unstable

view tools/examples/xeninfo.pl @ 16739:33dcf04d7715

tools/docs: Fix example and default IP addresses.

In various places in documentation and code, IP addresses are provided
as examples, defaults, or dummy configuration. In general the
specific IP addresses used in Xen are not always appropriate. (For
example, 1.2.3.4 is used in a few places!)

The following addresses should be used:
* For examples and documentation, 192.0.2.0/24. (See RFC3330.)
* For defaults for private networks, a random network from RFC1918.
I have randomly selected 172.30.206.0/24 for this purpose and
documented this in at the only registry I know of,
www.ucam.org/cam-grin. This network should henceforth be used for
default configurations of local bridges, test networks, etc. in
Xen tools.

The following addresses should NOT be used:
* 10.0.*.*, 10.1.*.*, 192.168.0.*, 192.168.1.*, etc. Using these
addresses gives greatly increased likelihood of collision, as
ignorant network administrators and reckless middlebox vendors
often pick networks from the bottom of 10/8 and 192.168/16.
* 169.254.*.*. These are reserved for zeroconf (ad-hoc networking)
and should not be used for Xen private networks, bridges, etc.,
etc. Use of these addresses by Xen scripts causes trouble on hosts
(eg laptops) which find themselves in ad-hoc networking
environments. I think this is not hypothetical (!) since at least
one Linux distribution have specific code to detect this case and
cause Xen startup to fail iff the host already has an external
zeroconf address.
* 1.2.3.4. WTF !?

I have also used 127.0.255.255 in one place where apparently a dummy
address is needed (some Linux kernels won't accept a lack of an NFS
server address). If 127.0.255.255 is mistakenly used it is unlikely
to do any damage to real traffic even if it does escape into the
network at large.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jan 17 15:13:40 2008 +0000 (2008-01-17)
parents 6145e5508d6b
children b51f9542ab14
line source
1 #!/usr/bin/perl -w
3 #############################################################################################################
4 # #
5 # Developed by Ingard Mev├ąg @ Oslo University College, spring 2007 #
6 # ingard [at] mevaag [dot] no #
7 # #
8 # This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 License. #
9 # To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter #
10 # to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. #
11 # #
12 #############################################################################################################
14 use strict;
15 # http://search.cpan.org/~rjray/RPC-XML-0.59/lib/RPC/XML/Client.pm
16 require RPC::XML;
17 require RPC::XML::Client;
19 # for debug purposes
20 #use Data::Dumper;
22 ##### CONFIG ######
24 my %xenhosts = ("192.0.2.10" => {"port" => "9363"},
25 "192.0.2.11" => {"port" => "9363"},
26 "192.0.2.12" => {"port" => "9363"},
27 "192.0.2.13" => {"port" => "9363"});
29 ##### CONFIG END ###
31 ##### STATIC VARS #####
32 my %host_info;
34 #######################
35 sub apiconnect
36 {
37 foreach my $xenhost (keys %xenhosts)
38 {
39 my $xen = RPC::XML::Client->new("http://$xenhost:$xenhosts{$xenhost}{'port'}");
40 my $session = $xen->simple_request("session.login_with_password", "user","");
41 if (! $session)
42 {
43 print "Can't connect to $xenhost :(\n";
44 $xenhosts{$xenhost} = {'xen' => $xen, 'session' => ""};
45 }
46 else
47 {
48 $xenhosts{$xenhost} = {'xen' => $xen, 'session' => $session->{'Value'}};
49 print "Connected successfully to $xenhost..\n";
50 }
51 }
52 }
54 sub validate_response
55 {
56 my ($result_ref) = @_;
57 if ($result_ref->{'Status'} eq "Success")
58 {
59 return $result_ref->{'Value'};
60 }
61 else
62 {
63 # status = Failure !
64 # die ("xmlrpc failed! ErrorDescription: $result_ref->{'ErrorDescription'}[1] -> $result_ref->{'ErrorDescription'}[0]");
65 print "xmlrpc failed! ErrorDescription: $result_ref->{'ErrorDescription'}[1] -> $result_ref->{'ErrorDescription'}[0]\n";
66 }
67 }
69 sub get_host_cpu_utilisation
70 {
71 my ($xen, $session, $host_name, $host_ref) = @_;
72 my $host_cpu_ref = validate_response($xen->simple_request("host.get_host_CPUs", $session, $host_ref));
73 foreach (@$host_cpu_ref)
74 {
75 my $host_cpu_utilisation = validate_response($xen->simple_request("host_cpu.get_utilisation", $session, $_));
76 $host_info{$host_name}{'cpus'}{$_} = $host_cpu_utilisation;
77 print " CPUiNFO: $host_cpu_utilisation\n";
78 }
79 }
81 sub get_host_pif_utilisation
82 {
83 my ($xen, $session, $host_name, $host_ref) = @_;
85 # This method isnt implemented yet it seems so using PIF.get_all for now..
86 # This will break when xen is made cluster aware..
87 # my $host_pif_ref = validate_response($xen->simple_request("host.get_PIFs", $session, $host_ref));
88 my $host_pif_ref = validate_response($xen->simple_request("PIF.get_all", $session));
89 foreach (@$host_pif_ref)
90 {
91 my $host_pif_device = validate_response($xen->simple_request("PIF.get_device", $session, $_));
92 my $host_pif_metrics_ref = validate_response($xen->simple_request("PIF.get_metrics", $session, $_));
94 # Whats the best solution performancewise?
95 # Collecting stats from get_records, or pulling individually?
97 # my $host_pif_record = validate_response($xen->simple_request("PIF_metrics.get_record", $session, $host_pif_metrics_ref));
98 # my $host_pif_io_read = $host_pif_record->{'io_read_kbs'};
99 # my $host_pif_io_write = $host_pif_record->{'io_write_kbs'};
100 my $host_pif_io_read = validate_response($xen->simple_request("PIF_metrics.get_io_read_kbs", $session, $host_pif_metrics_ref));
101 my $host_pif_io_write = validate_response($xen->simple_request("PIF_metrics.get_io_write_kbs", $session, $host_pif_metrics_ref));
103 $host_info{$host_name}{'pifs'}{$host_pif_device} = {'read' => $host_pif_io_read, 'write' => $host_pif_io_write};
104 print " PiFiNFO: $host_pif_device READ: $host_pif_io_read - WRITE: $host_pif_io_write\n";
105 # $host_info{$host_name}{'pifs'}{$host_pif_device}{'read'} = $host_pif_io_read;
106 # $host_info{$host_name}{'pifs'}{$host_pif_device}{'write'} = $host_pif_io_write;
107 }
108 }
110 sub get_host_mem_utilisation
111 {
112 my ($xen, $session, $host_name, $host_ref) = @_;
113 my $host_metrics_ref = validate_response($xen->simple_request("host.get_metrics", $session, $host_ref));
114 my $host_mem_total = validate_response($xen->simple_request("host_metrics.get_memory_total", $session, $host_metrics_ref)) / 1024 / 1024;
115 my $host_mem_free = validate_response($xen->simple_request("host_metrics.get_memory_free", $session, $host_metrics_ref)) / 1024 / 1024;
116 $host_info{$host_name}{'memory'} = {'total' => $host_mem_total, 'free' => $host_mem_free};
117 print " MEMiNFO: Total: $host_mem_total MB - Free: $host_mem_free MB\n";
118 }
120 sub get_vm_mem_info
121 {
122 my ($xen, $session, $host_name, $vm_ref, $vm_name_label) = @_;
123 my $vm_mem_stat_max = validate_response($xen->simple_request("VM.get_memory_static_max",$session,$vm_ref));
124 my $vm_mem_stat_min = validate_response($xen->simple_request("VM.get_memory_static_min",$session,$vm_ref));
125 my $vm_mem_dyn_max = validate_response($xen->simple_request("VM.get_memory_dynamic_max",$session,$vm_ref));
126 my $vm_mem_dyn_min = validate_response($xen->simple_request("VM.get_memory_dynamic_min",$session,$vm_ref));
128 # not implemented yet.. We'll do this at the same time as getting cpu utilisation
129 # in the get_vm_metrics sub instead..
130 #my $vm_metrics_ref = validate_response($xen->simple_request("VM.get_metrics",$session,$vm_ref));
131 #my $vm_mem_actual = validate_response($xen->simple_request("VM_metrics.get_memory_actual",$session,$vm_metrics_ref));
133 $host_info{$host_name}{'vms'}{$vm_name_label}{'memory'} = {'static_max' => $vm_mem_stat_max,
134 'static_min' => $vm_mem_stat_min,
135 'dynamic_max' => $vm_mem_dyn_max,
136 'dynamic_min' => $vm_mem_dyn_min};
138 # xm list uses the dynamic min var as far as i can tell.. or?
139 # Lets print the memactual info instead of this... I'll do that in the get_vm_metrics sub instead..
140 # print " |- MEMiNFO: Dynamic Min: $vm_mem_dyn_min - Actually in use: $vm_mem_actual\n";
141 }
143 sub get_vm_metrics
144 {
145 my ($xen, $session, $host_name, $vm_ref, $vm_name_label) = @_;
146 my $vm_metrics_ref = validate_response($xen->simple_request("VM.get_metrics",$session,$vm_ref));
148 my %vm_vcpu_utilisation = %{validate_response($xen->simple_request("VM_metrics.get_vcpus_utilisation",$session,$vm_metrics_ref))};
149 for my $tempcpu (keys %vm_vcpu_utilisation)
150 {
151 print " |- CPUiNFO: $tempcpu - $vm_vcpu_utilisation{$tempcpu}\n";
152 $host_info{$host_name}{'vms'}{$vm_name_label}{'vcpus'} = {$tempcpu => $vm_vcpu_utilisation{$tempcpu}};
153 }
154 my $vm_mem_actual = validate_response($xen->simple_request("VM_metrics.get_memory_actual",$session,$vm_metrics_ref)) / 1024 / 1024;
155 $host_info{$host_name}{'vms'}{$vm_name_label}{'memory'}{'actual'} = "$vm_mem_actual";
156 print " |- MEMiNFO: Actually in use: $vm_mem_actual MB\n";
157 }
159 sub get_vm_vif_utilisation
160 {
161 my ($xen, $session, $host_name, $vm_ref, $vm_name_label) = @_;
162 my $vm_vifs = validate_response($xen->simple_request("VM.get_VIFs",$session,$vm_ref));
163 foreach (@$vm_vifs)
164 {
165 my $vif_device = validate_response($xen->simple_request("VIF.get_device",$session,$_));
166 my $vif_io_read = validate_response($xen->simple_request("VIF_metrics.get_io_read_kbs", $session, $_));
167 my $vif_io_write = validate_response($xen->simple_request("VIF_metrics.get_io_write_kbs", $session, $_));
168 $host_info{$host_name}{'vms'}{$vm_name_label}{'vifs'}{$vif_device} = {'read' => $vif_io_read, 'write' => $vif_io_write};
169 print " |- ViFiNFO: $vif_device READ: $vif_io_read - WRITE: $vif_io_write\n";
170 }
171 }
173 sub get_vm_vbd_utilisation
174 {
175 my ($xen, $session, $host_name, $vm_ref, $vm_name_label) = @_;
176 my $vm_vbds = validate_response($xen->simple_request("VM.get_VBDs",$session,$vm_ref));
177 foreach (@$vm_vbds)
178 {
179 my $vbd_device = validate_response($xen->simple_request("VBD.get_device",$session,$_));
180 my $vbd_io_read = validate_response($xen->simple_request("VBD_metrics.get_io_read_kbs", $session, $_));
181 my $vbd_io_write = validate_response($xen->simple_request("VBD_metrics.get_io_write_kbs", $session, $_));
182 $host_info{$host_name}{'vms'}{$vm_name_label}{'vbds'}{$vbd_device} = {'read' => $vbd_io_read, 'write' => $vbd_io_write};
183 print " |- VBDiNFO: $vbd_device READ: $vbd_io_read - WRITE: $vbd_io_write\n";
184 }
185 }
188 sub get_vm_type
189 {
190 my ($xen, $session, $host_name, $vm_ref, $vm_name_label) = @_;
191 # not running response through validate_response() here to stop it from crashing..
192 #
193 # api docs says if this (following) field is set, its a HVM domain.
194 my $vm_bootloader_results = $xen->simple_request("VM.get_HVM_boot_policy",$session,$vm_ref);
195 if ("$vm_bootloader_results->{'Status'}" eq "Success")
196 {
197 if ("$vm_bootloader_results->{'Value'}" ne "")
198 {
199 $host_info{$host_name}{'vms'}{$vm_name_label}{'type'} = "HVM";
200 }
201 else
202 {
203 $host_info{$host_name}{'vms'}{$vm_name_label}{'type'} = "PV";
204 }
205 }
206 else
207 {
208 # However, xen 3.0.4 doest support this part of the api, so afaik I can get the difference with:
209 my $vm_pv_kernel_results = $xen->simple_request("VM.get_PV_kernel",$session,$vm_ref);
210 # which is something like:
211 # 'PV_kernel': '/boot/vmlinuz-2.6.18-xen',
212 # or
213 # 'PV_kernel': '/usr/lib/xen/boot/hvmloader',
214 if ("$vm_pv_kernel_results->{'Value'}" =~ m/hvm/i)
215 {
216 $host_info{$host_name}{'vms'}{$vm_name_label}{'type'} = "HVM";
217 }
218 else
219 {
220 $host_info{$host_name}{'vms'}{$vm_name_label}{'type'} = "PV";
221 }
222 }
223 }
225 sub get_complete_info
226 {
227 my %all_vms;
228 foreach my $xenhost (sort keys %xenhosts)
229 {
230 next unless $xenhosts{$xenhost}{'session'};
231 my $xen = $xenhosts{$xenhost}{'xen'};
232 my $session = $xenhosts{$xenhost}{'session'};
233 print "_______________________\n## $xenhost ##\n-----------------------\n";
235 my $host_ref = validate_response($xen->simple_request("session.get_this_host", $session));
237 my $host_name = validate_response($xen->simple_request("host.get_name_label", $session, $host_ref));
238 $xenhosts{$xenhost}{'hostname'} = $host_name;
239 $host_info{$host_name}{'ip'} = $xenhost;
241 get_host_cpu_utilisation($xen, $session, $host_name, $host_ref);
243 get_host_mem_utilisation($xen, $session, $host_name, $host_ref);
245 get_host_pif_utilisation($xen, $session, $host_name, $host_ref);
248 my $all_vm_refs = validate_response($xen->simple_request("host.get_resident_VMs",$session, $host_ref));
250 foreach my $vm_ref (@$all_vm_refs)
251 {
252 my $vm_name_label = validate_response($xen->simple_request("VM.get_name_label",$session,$vm_ref));
253 get_vm_type($xen,$session,$host_name,$vm_ref,$vm_name_label);
255 my $vm_id = validate_response($xen->simple_request("VM.get_domid",$session,$vm_ref));
257 print "vm: $vm_id\t$vm_name_label\ttype: $host_info{$host_name}{'vms'}->{$vm_name_label}{'type'}\n";
259 # vm_metrics includes both mem_actual & cpu utilisation
260 # So we'll add all stats found in that class in one go..
261 get_vm_metrics($xen,$session,$host_name,$vm_ref,$vm_name_label);
262 # get_vm_cpu_utilisation($xen,$session,$host_name,$vm_ref,$vm_name_label);
264 # all other mem stats are added seperately..
265 # This might not be needed at all as xen doesnt have functionality to
266 # resize mem for a VM atm (afaik)
267 get_vm_mem_info($xen,$session,$host_name,$vm_ref,$vm_name_label);
269 get_vm_vif_utilisation($xen,$session,$host_name,$vm_ref,$vm_name_label);
271 get_vm_vbd_utilisation($xen,$session,$host_name,$vm_ref,$vm_name_label);
273 $all_vms{$vm_name_label} = "" unless ("$vm_name_label" eq "Domain-0");
274 }
275 print "\n";
276 }
277 # Debug: Uncomment to see the nested datastructure..
278 #print Dumper(%host_info);
279 }
283 apiconnect();
284 get_complete_info();