Documentation fixes.
[virt-hostinfo.git] / hostinfo-status / hostinfo-status.pl
1 #!/usr/bin/perl -w
2 # @configure_input@
3 # virt-hostinfo
4 # Copyright (C) 2009 Red Hat Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 use strict;
21
22 use Pod::Usage;
23 use Getopt::Long;
24 use Sys::Virt;
25 use XML::XPath;
26 use XML::XPath::XMLParser;
27
28 =head1 NAME
29
30 hostinfo-status - check if hostinfo is enabled for a guest
31
32 =head1 SYNOPSIS
33
34  hostinfo-status [GUESTNAME [GUESTNAME...]]
35
36 =head1 DESCRIPTION
37
38 This command finds out if hostinfo is enabled or disabled for a
39 particular guest.
40
41 For example:
42
43  # hostinfo-status myguest
44  myguest: hostinfo is enabled on serial port 1 (ttyS1, COM2)
45
46  # hostinfo-status anotherguest
47  anotherguest: hostinfo is disabled
48
49 If no guest names are listed on the command line, this command
50 displays the status of all guests known to libvirt.
51
52 If you want to find out if the hostinfo feature is enabled for the
53 host as a whole, you should use this command instead:
54
55  service hostinfo status
56
57 (see L<hostinfo(8)>).
58
59 =head1 OPTIONS
60
61 =over 4
62
63 =cut
64
65 my $help;
66
67 =item B<--help>
68
69 Display brief help.
70
71 =cut
72
73 my $version;
74
75 =item B<--version>
76
77 Display version number and exit.
78
79 =cut
80
81 my $uri;
82
83 =item B<--connect URI> | B<-c URI>
84
85 Connect to libvirt using the given URI.  If omitted then
86 we connect to the default libvirt hypervisor.
87
88 =cut
89
90 my $quiet;
91
92 =item B<--quiet>
93
94 Use this option from scripts to test if hostinfo is enabled
95 for a single guest without the verbose messages:
96
97  if hostinfo-status --quiet myguest; then
98    echo Yes, hostinfo is enabled for this guest.
99  else
100    echo No, hostinfo is not enabled for this guest.
101  fi
102
103 =back
104
105 =cut
106
107 GetOptions ("help|?" => \$help,
108             "version" => \$version,
109             "connect|c=s" => \$uri,
110             "quiet" => \$quiet,
111     ) or pod2usage (2);
112 pod2usage (1) if $help;
113 if ($version) {
114     print "@VERSION@\n";
115     exit
116 }
117
118 sub main
119 {
120     my $ret = 0;
121
122     # Connect to libvirt.
123     my @libvirt_params = (readonly => 1);
124     push @libvirt_params, address => $uri if $uri;
125     my $conn = Sys::Virt->new (@libvirt_params);
126     die "could not connect to libvirt daemon" unless $conn;
127
128     # Get domains we're going to examine.
129     my @names = @ARGV;
130     my @doms;
131     if (@names == 0) {
132         die "'--quiet' option given with no guest names" if $quiet;
133         @doms = $conn->list_domains ();
134         push @doms, $conn->list_defined_domains ();
135     } else {
136         die "'--quiet' option given with more than one guest name"
137             if $quiet && @names > 1;
138         @doms = map { $conn->get_domain_by_name ($_) } @names;
139     }
140
141     # Examine each domain.
142     foreach my $dom (@doms) {
143         my $name = $dom->get_name;
144         my $xml = $dom->get_xml_description ();
145         my $path = XML::XPath->new (xml => $xml);
146
147         # Get all <serial type='unix'> devices.
148         my @serials =
149             $path->findnodes (q{//devices/serial[@type='unix']});
150
151         # Get the zero/one serial port which looks like a hostinfo device.
152         # It's an error if a domain has more than one of these.
153         my $errors = 0;
154         my $hostinfo_serial;
155         my $hostinfo_port;
156
157         foreach my $serial (@serials) {
158             my $spath =
159                 XML::XPath->new (xml =>
160                                  XML::XPath::XMLParser::as_string ($serial));
161
162             # Check it's a hostinfo serial port.
163             my @srcs =
164                 $spath->findnodes (q{//source[starts-with(@path,"@localstatedir@/lib/hostinfo")]});
165             next if @srcs == 0;
166
167             if (@srcs > 1) {
168                 warn "error: $name: malformed domain XML: multiple <source path> elements\n";
169                 $errors++;
170                 next;
171             }
172
173             unless ($hostinfo_serial) {
174                 $hostinfo_serial = $serial;
175             } else {
176                 warn "error: $name: domain appears to have multiple hostinfo serial ports\n";
177                 $errors++;
178                 next;
179             }
180
181             # Get the target port.
182             my @targports =
183                 $spath->findnodes (q{//target/@port});
184             if (@targports == 0) {
185                 warn "error: $name: malformed domain XML: no <target port> elements\n";
186                 $errors++;
187                 next;
188             }
189             if (@targports > 1) {
190                 warn "error: $name: malformed domain XML: multiple <target port> elements\n";
191                 $errors++;
192                 next;
193             }
194             $hostinfo_port = $targports[0]->getData;
195         }
196
197         if ($quiet) {
198             $ret = $errors ? 2 : defined ($hostinfo_serial) ? 0 : 1;
199         } else {
200             if ($hostinfo_serial) {
201                 if (defined $hostinfo_port) {
202                     my $windows_port = $hostinfo_port+1;
203                     print "$name: hostinfo is enabled on serial port $hostinfo_port (ttyS$hostinfo_port, COM$windows_port)\n";
204                 } else {
205                     print "$name: hostinfo is enabled on an undefined serial port\n";
206                 }
207             } else {
208                 print "$name: hostinfo is disabled\n";
209             }
210         }
211     }
212
213     $ret;
214 }
215
216 =head1 RETURN VALUE
217
218 Normally C<hostinfo-status> returns 0 if the command was successful,
219 or 2 if there was an error.
220
221 However if you use the C<--quiet> option, it returns 0 if hostinfo
222 is enabled, 1 if hostinfo is disabled, or 2 if there was an error.
223
224 =cut
225
226 my $ret = eval { &main };
227 if ($@) {
228     print STDERR "$@\n";
229     exit 2;
230 }
231 exit $ret if $quiet;
232 exit 0;
233
234 =head1 SEE ALSO
235
236 L<hostinfo(8)>,
237 L<hostinfo-set(8)>,
238 L<hostinfo-test(8)>,
239 L<virt-install(1)>,
240 L<virt-manager(1)>,
241 L<http://fedoraproject.org/wiki/Features/Hostinfo>,
242 L<http://libvirt.org/>.
243
244 =head1 AUTHORS
245
246 Richard W.M. Jones (C<rjones at redhat dot com>)
247
248 =head1 COPYRIGHT
249
250 Copyright (C) 2009 Red Hat Inc.
251 L<http://fedoraproject.org/wiki/Features/Hostinfo>
252
253 This program is free software; you can redistribute it and/or modify
254 it under the terms of the GNU General Public License as published by
255 the Free Software Foundation; either version 2 of the License, or
256 (at your option) any later version.
257
258 This program is distributed in the hope that it will be useful,
259 but WITHOUT ANY WARRANTY; without even the implied warranty of
260 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
261 GNU General Public License for more details.
262
263 You should have received a copy of the GNU General Public License
264 along with this program; if not, write to the Free Software
265 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.