File Coverage

blib/lib/FusionInventory/Agent/SOAP/VMware.pm
Criterion Covered Total %
statement 24 136 17.6
branch 0 34 0.0
condition 0 5 0.0
subroutine 8 16 50.0
pod 4 4 100.0
total 36 195 18.4


line stmt bran cond sub pod time code
1             package FusionInventory::Agent::SOAP::VMware;
2              
3 2     2   3273256 use strict;
  2         9  
  2         96  
4 2     2   13 use warnings;
  2         4  
  2         88  
5              
6 2     2   8 use English qw(-no_match_vars);
  2         30  
  2         26  
7 2     2   1626 use XML::TreePP;
  2         9571  
  2         31  
8 2     2   757 use LWP::UserAgent;
  2         32163  
  2         21  
9 2     2   1011 use HTTP::Cookies;
  2         10793  
  2         23  
10              
11 2     2   477 use FusionInventory::Agent;
  2         5  
  2         13  
12 2     2   844 use FusionInventory::Agent::SOAP::VMware::Host;
  2         4  
  2         23  
13              
14             sub new {
15 0     0 1   my ($class, %params) = @_;
16              
17 0           my $self = {
18             url => $params{url},
19             tpp => XML::TreePP->new(force_array => [qw(returnval propSet)]),
20             };
21 0           bless $self, $class;
22              
23             # create user agent
24 0   0       $self->{ua} = LWP::UserAgent->new(
25             requests_redirectable => ['POST', 'GET', 'HEAD'],
26             agent => $FusionInventory::Agent::AGENT_STRING,
27             timeout => $params{timeout} || 180,
28             ssl_opts => { verify_hostname => 0 },
29             cookie_jar => HTTP::Cookies->new(ignore_discard => 1),
30             );
31              
32 0           return $self;
33             }
34              
35             sub _send {
36 0     0     my ( $self, $action, $xmlToSend ) = @_;
37              
38 0           my $req = HTTP::Request->new( POST => $self->{url} );
39 0           $req->content($xmlToSend);
40 0           $req->{_headers}->{soapaction} = "\"urn:vim25#" . $action . "\"";
41 0           $req->{_headers}->{accept} = [ 'text/xml', 'application/soap' ];
42 0           $req->{_headers}->{'content-length'} = length($xmlToSend);
43 0           $req->{_protocol} = 'HTTP/1.1';
44 0           $req->content_type('text/xml; charset=utf-8');
45              
46 0           my $res = $self->{ua}->request($req);
47              
48 0 0         if ( $res->is_success ) {
49 0           return $res->content;
50             } else {
51 0           my $err = $res->content;
52 0           my $tmpRef = {};
53              
54 0           eval {
55 0           $err =~ s/.*(.*<\/faultstring>).*/$1/sg;
56 0           $tmpRef = $self->{tpp}->parse($err);
57             };
58              
59 0           my $errorString = $res->status_line;
60 0 0 0       if ( $tmpRef && $tmpRef->{faultstring} ) {
61 0           $errorString .= ": " . $tmpRef->{faultstring};
62             }
63 0           print STDERR $errorString . "\n";
64 0           $self->{lastError} = $errorString;
65 0           return;
66             }
67              
68 0           return 1;
69             }
70              
71             sub _parseAnswer {
72 0     0     my ( $self, $answer ) = @_;
73              
74 0 0         return unless $answer;
75              
76 0           local $INPUT_RECORD_SEPARATOR; # Set input to "slurp" mode.
77              
78             # We simplify the XML structure
79 0           my $pattern = '.*<\w+Response xmlns="urn:vim25">(.+).*$';
80 0           $answer =~ s/$pattern/$1/sg,;
81 0           $answer =~ s/ (xsi:|)type="[:\w]+"//sg;
82 0           $answer =~ s/[[:cntrl:]]//g;
83 0           my $tmpRef = $self->{tpp}->parse($answer);
84              
85 0           my $ref = [];
86 0           foreach ( @{ $tmpRef->{returnval} } ) {
  0            
87 0 0         if ( $_->{propSet} ) {
88 0           my %tmp;
89 0           foreach my $p ( @{ $_->{propSet} } ) {
  0            
90 0 0         next unless $p->{val};
91 0           $tmp{ $p->{name} } = $p->{val};
92             }
93 0           push @$ref, \%tmp;
94             } else {
95 0           push @$ref, $_;
96             }
97             }
98              
99 0           return $ref;
100              
101             }
102              
103             sub connect {
104 0     0 1   my ( $self, $user, $password ) = @_;
105              
106 0           my $req = '
107            
108             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
109             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
110            
111             <_this type="ServiceInstance">ServiceInstance
112             ';
113              
114 0           my $answer = $self->_send( 'ServiceInstance', $req );
115 0 0         return unless $answer;
116              
117 0           my $serviceInstance = $self->_parseAnswer($answer);
118 0 0         return unless $serviceInstance;
119              
120 0 0         if ( $serviceInstance->[0]{about}{apiType} eq 'VirtualCenter' ) {
121 0           $self->{vcenter} = 1; # TODO
122 0           $self->{sessionManager} = "SessionManager";
123 0           $self->{propertyCollector} = "propertyCollector";
124             } else {
125 0           $self->{vcenter} = 0;
126 0           $self->{sessionManager} = "ha-sessionmgr";
127 0           $self->{propertyCollector} = "ha-property-collector";
128             }
129              
130 0           $req = '
131            
132             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
133             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
134            
135             <_this type="SessionManager">%s
136             %s%s';
137              
138 0           $answer = $self->_send(
139             'Login',
140             sprintf( $req, $self->{sessionManager}, $user, $password )
141             );
142 0 0         return unless $answer;
143 0 0         return if $answer =~ /ServerFaultCode/m;
144              
145 0           return $self->_parseAnswer($answer);
146              
147             }
148              
149             #sub getHostInfo {
150             # my ($self) = @_;
151             #
152             #
153             # my $req =
154             # '<_this type="ServiceInstance">ServiceInstance';
155             #
156             #
157             # my $answer = $self->_send('RetrieveServiceContent', 'RetrieveServiceContent', $req);
158             # my $ref = $self->_parseAnswer($answer);
159             #
160             # return $host;
161             #}
162              
163             sub _getVirtualMachineList {
164 0     0     my ($self) = @_;
165              
166 0           my $req =
167              
168             '
169            
170             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
171             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
172            
173             <_this type="PropertyCollector">ha-property-collector
174             VirtualMachine0ha-folder-root
175             0folderTraversalSpecFolderchildEntity0folderTraversalSpecdatacenterHostTraversalSpecdatacenterVmTraversalSpecdatacenterDatastoreTraversalSpecdatacenterNetworkTraversalSpeccomputeResourceRpTraversalSpeccomputeResourceHostTraversalSpechostVmTraversalSpecresourcePoolVmTraversalSpecdatacenterDatastoreTraversalSpecDatacenterdatastoreFolder0folderTraversalSpecdatacenterNetworkTraversalSpecDatacenternetworkFolder0folderTraversalSpecdatacenterVmTraversalSpecDatacentervmFolder0folderTraversalSpecdatacenterHostTraversalSpecDatacenterhostFolder0folderTraversalSpeccomputeResourceHostTraversalSpecComputeResourcehost0computeResourceRpTraversalSpecComputeResourceresourcePool0resourcePoolTraversalSpecresourcePoolVmTraversalSpecresourcePoolTraversalSpecResourcePoolresourcePool0resourcePoolTraversalSpecresourcePoolVmTraversalSpechostVmTraversalSpecHostSystemvm0folderTraversalSpecresourcePoolVmTraversalSpecResourcePoolvm0
176             ';
177              
178 0           my $answer = $self->_send(
179             'RetrievePropertiesVMList',
180             $req
181             );
182 0           my $ref = $self->_parseAnswer($answer);
183 0           my @list;
184 0 0         if ( ref($ref) eq 'HASH' ) {
    0          
185 0           push @list, $ref;
186             }
187             elsif ($ref) {
188 0           @list = @{$ref};
  0            
189             }
190              
191 0           my @ids;
192 0           foreach (@list) {
193 0           push @ids, $_->{obj};
194             }
195              
196 0           return \@ids;
197              
198             }
199              
200             sub _getVirtualMachineById {
201 0     0     my ( $self, $id ) = @_;
202              
203 0           my $req = '
204            
205             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
206             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
207            
208             <_this type="PropertyCollector">%s
209             VirtualMachine1%s
210            
211             ';
212              
213 0           my $answer = $self->_send(
214             'RetrieveProperties',
215             sprintf( $req, $self->{propertyCollector}, $id )
216             );
217 0 0         return [] unless $answer;
218              
219             # hack to preserve annotation / comment formating
220 0           $answer =~ s/\n/ /gm;
221              
222 0           my $ref = $self->_parseAnswer($answer);
223 0           return $ref;
224             }
225              
226             sub getHostFullInfo {
227 0     0 1   my ( $self, $id ) = @_;
228              
229 0 0         $id = 'ha-host' unless $id;
230              
231 0           my $req = '
232            
233             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
234             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
235            
236             <_this type="PropertyCollector">%s
237             HostSystem1%s
238            
239             ';
240              
241 0           my $answer = $self->_send(
242             'RetrieveProperties',
243             sprintf( $req, $self->{propertyCollector}, $id )
244             );
245 0           my $ref = $self->_parseAnswer($answer);
246 0           my $vms = [];
247 0           my $machineIdList;
248 0 0         if ( exists( $ref->[0]{vm}{ManagedObjectReference} ) ) { # ESX 3.5
249 0 0         if ( ref( $ref->[0]{vm}{ManagedObjectReference} ) eq 'ARRAY' ) {
250 0           $machineIdList = $ref->[0]{vm}{ManagedObjectReference};
251             } else {
252 0           push @$machineIdList, $ref->[0]{vm}{ManagedObjectReference};
253             }
254             } else {
255 0           $machineIdList = $self->_getVirtualMachineList();
256             }
257              
258             #$vm = $ref->[0]{vm};
259 0           foreach my $id (@$machineIdList) {
260 0           push @$vms, $self->_getVirtualMachineById($id);
261             }
262              
263 0           my $host = FusionInventory::Agent::SOAP::VMware::Host->new(
264             hash => $ref, vms => $vms
265             );
266 0           return $host;
267             }
268              
269             sub getHostIds {
270 0     0 1   my ($self) = @_;
271              
272 0 0         if ( !$self->{vcenter} ) {
273 0           return ['ha-host'];
274             }
275              
276 0           my $req = '
277            
278             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
279             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
280            
281             <_this type="PropertyCollector">propertyCollector
282             HostSystem0group-d1
283             0folderTraversalSpecFolderchildEntity0folderTraversalSpecdatacenterHostTraversalSpecdatacenterVmTraversalSpecdatacenterDatastoreTraversalSpecdatacenterNetworkTraversalSpeccomputeResourceRpTraversalSpeccomputeResourceHostTraversalSpechostVmTraversalSpecresourcePoolVmTraversalSpecdatacenterDatastoreTraversalSpecDatacenterdatastoreFolder0folderTraversalSpecdatacenterNetworkTraversalSpecDatacenternetworkFolder0folderTraversalSpecdatacenterVmTraversalSpecDatacentervmFolder0folderTraversalSpecdatacenterHostTraversalSpecDatacenterhostFolder0folderTraversalSpeccomputeResourceHostTraversalSpecComputeResourcehost0computeResourceRpTraversalSpecComputeResourceresourcePool0resourcePoolTraversalSpecresourcePoolVmTraversalSpecresourcePoolTraversalSpecResourcePoolresourcePool0resourcePoolTraversalSpecresourcePoolVmTraversalSpechostVmTraversalSpecHostSystemvm0folderTraversalSpecresourcePoolVmTraversalSpecResourcePoolvm0';
284              
285 0           my $answer = $self->_send('RetrieveProperties', sprintf($req) );
286 0           my $ref = $self->_parseAnswer($answer);
287              
288 0           my @ids;
289 0           foreach (@$ref) {
290 0           push @ids, $_->{obj};
291             }
292              
293 0           return \@ids;
294             }
295              
296             1;
297              
298             __END__