File Coverage

lib/Rex/Virtualization/LibVirt/guestinfo.pm
Criterion Covered Total %
statement 35 84 41.6
branch 0 14 0.0
condition 0 9 0.0
subroutine 12 13 92.3
pod 0 1 0.0
total 47 121 38.8


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             package Rex::Virtualization::LibVirt::guestinfo;
6              
7 1     1   15 use v5.12.5;
  1         3  
8 1     1   8 use warnings;
  1         2  
  1         42  
9              
10             our $VERSION = '1.14.3'; # VERSION
11              
12 1     1   5 use Data::Dumper;
  1         2  
  1         54  
13 1     1   7 use Rex::Logger;
  1         3  
  1         6  
14 1     1   21 use Rex::Helper::Run;
  1         9  
  1         59  
15 1     1   6 use Rex::Helper::Path;
  1         3  
  1         71  
16 1     1   12 use Rex::Virtualization::LibVirt::iflist;
  1         4  
  1         12  
17 1     1   28 use Rex::Commands::Gather;
  1         4  
  1         8  
18 1     1   7 use Rex::Virtualization::LibVirt::info;
  1         2  
  1         7  
19 1     1   24 use Rex::Interface::File;
  1         2  
  1         6  
20 1     1   21 use Rex::Interface::Exec;
  1         2  
  1         25  
21 1     1   27 use JSON::MaybeXS;
  1         2  
  1         657  
22             require Rex::Commands::Run;
23              
24             sub execute {
25 0     0 0   my ( $class, $vmname ) = @_;
26              
27 0 0         unless ($vmname) {
28 0           die("You have to define the vm name!");
29             }
30              
31 0           Rex::Logger::debug("Getting info of guest: $vmname");
32              
33 0           my $info = Rex::Virtualization::LibVirt::info->execute($vmname);
34 0 0         if ( $info->{State} eq "shut off" ) {
35 0           return {};
36             }
37              
38 0           my @ifaces;
39              
40 0 0 0       if ( Rex::Config::get_use_rex_kvm_agent
      0        
41             && exists $info->{has_kvm_agent_on_port}
42             && $info->{has_kvm_agent_on_port} )
43             {
44              
45 0           my $got_ip = 0;
46              
47 0           while ( $got_ip == 0 ) {
48              
49 0           my $fh = Rex::Interface::File->create();
50 0           my $rnd_file = get_tmp_file;
51              
52 0           my $content = q|
53             use strict;
54             use warnings;
55              
56             unlink $0;
57              
58             use IO::Socket::INET;
59              
60             my $sock;
61              
62             while(! $sock) {
63             $sock = IO::Socket::INET->new(PeerHost => '127.0.0.1', PeerPort => $ARGV[0], Proto => 'tcp');
64             sleep 1;
65             }
66              
67             my $got_info = 0;
68             my $try = 0;
69             while($got_info == 0) {
70             eval {
71             local $SIG{ALRM} = sub { die; };
72             alarm 3;
73             if($try >= 10) {
74             exit 1;
75             }
76              
77             $try++;
78             print $sock "GET /network/devices\n";
79              
80             my $line = <$sock>;
81             $line = <$sock>;
82             $line =~ s/[\r\n]//gms;
83             if($line =~ m/^\{"networkdevices/) {
84             print "$line\n";
85             $got_info++;
86             }
87             alarm 0;
88             };
89             }
90             |;
91              
92 0           $fh->open( ">", $rnd_file );
93 0           $fh->write($content);
94 0           $fh->close;
95              
96 0           my $exec = Rex::Interface::Exec->create();
97 0           my ($data) = $exec->exec("perl $rnd_file $info->{has_kvm_agent_on_port}");
98              
99 0 0         if ( $? == 1 ) {
100              
101             # can't connect to agent
102 0           $info->{has_kvm_agent_on_port} = 0;
103 0           last;
104             }
105              
106 0           my $ref = decode_json($data);
107 0           delete $ref->{networkconfiguration}->{lo};
108              
109 0           for my $net ( keys %{ $ref->{networkconfiguration} } ) {
  0            
110             push @ifaces,
111             {
112             device => $net,
113 0           %{ $ref->{networkconfiguration}->{$net} },
  0            
114             };
115             }
116              
117 0 0         if ( $ifaces[0]->{ip} ) {
118 0           $got_ip++;
119             }
120             else {
121 0           @ifaces = ();
122 0           sleep 1;
123             }
124             }
125              
126             }
127              
128 0 0         if ( !$info->{has_kvm_agent_on_port} ) {
129              
130 0           my $ifs = Rex::Virtualization::LibVirt::iflist->execute($vmname);
131              
132 0           my $got_ip = 0;
133              
134             # search arp in different locations.
135             # sometimes there is not PATH for normal users to /sbin commands.
136             # and also arp can be in different locations.
137 0           my $command =
138             Rex::Commands::Run::can_run( "/sbin/arp", "/usr/sbin/arp", "arp" );
139              
140 0           while ( $got_ip < scalar( keys %{$ifs} ) ) {
  0            
141             my %arp =
142             map {
143 0           my @x = ( $_ =~ m/\(([^\)]+)\) at ([^\s]+)\s/ );
  0            
144 0           ( $x[1], $x[0] )
145             } i_run "$command -an", fail_ok => 1;
146              
147 0           for my $if ( keys %{$ifs} ) {
  0            
148 0 0 0       if ( exists $arp{ $ifs->{$if}->{mac} } && $arp{ $ifs->{$if}->{mac} } ) {
149 0           $got_ip++;
150             push @ifaces,
151             {
152             device => $if,
153             ip => $arp{ $ifs->{$if}->{mac} },
154 0           %{ $ifs->{$if} }
  0            
155             };
156             }
157             }
158              
159 0           sleep 1;
160             }
161              
162             }
163              
164 0           return { network => \@ifaces, };
165             }
166              
167             1;