File Coverage

blib/lib/FusionInventory/Agent/Task/Deploy/File.pm
Criterion Covered Total %
statement 44 91 48.3
branch 6 38 15.7
condition 1 14 7.1
subroutine 10 13 76.9
pod 0 5 0.0
total 61 161 37.8


line stmt bran cond sub pod time code
1             package FusionInventory::Agent::Task::Deploy::File;
2              
3 4     4   40262038 use strict;
  4         21  
  4         216  
4 4     4   30 use warnings;
  4         17  
  4         190  
5              
6 4     4   1979 use Digest::SHA;
  4         9349  
  4         216  
7 4     4   27 use File::Basename;
  4         9  
  4         406  
8 4     4   19 use File::Path qw(mkpath);
  4         9  
  4         273  
9 4     4   22 use File::Glob;
  4         7  
  4         201  
10 4     4   1594 use HTTP::Request;
  4         49659  
  4         51  
11              
12             sub new {
13 1     1 0 1421 my ($class, %params) = @_;
14              
15 1 50       5 die "no datastore parameter" unless $params{datastore};
16 1 50       6 die "no sha512 parameter" unless $params{sha512};
17              
18             my $self = {
19             p2p => $params{data}->{p2p},
20             retention_duration => $params{data}->{'p2p-retention-duration'} || 60 * 24 * 3,
21             uncompress => $params{data}->{uncompress},
22             mirrors => $params{data}->{mirrors},
23             multiparts => $params{data}->{multiparts},
24             name => $params{data}->{name},
25             sha512 => $params{sha512},
26             datastore => $params{datastore},
27             client => $params{client},
28             logger => $params{logger}
29 1   50     19 };
30              
31 1         3 bless $self, $class;
32              
33 1         3 return $self;
34             }
35              
36             sub getPartFilePath {
37 4     4 0 414 my ($self, $sha512) = @_;
38              
39 4 50       18 return unless $sha512 =~ /^(.)(.)(.{6})/;
40 4         24 my $subFilePath = $1.'/'.$2.'/'.$3;
41              
42             my @storageDirs =
43             File::Glob::glob($self->{datastore}->{path}.'/fileparts/shared/*'),
44 4         303 File::Glob::glob($self->{datastore}->{path}.'/fileparts/private/*');
45              
46 4         11 foreach my $dir (@storageDirs) {
47 0 0       0 if (-f $dir.'/'.$subFilePath) {
48 0         0 return $dir.'/'.$subFilePath;
49             }
50             }
51              
52 4         9 my $filePath = $self->{datastore}->{path}.'/fileparts/';
53             # filepart not found
54 4 50       12 if ($self->{p2p}) {
55 0         0 $filePath .= 'shared/';
56             } else {
57 4         9 $filePath .= 'private/';
58             }
59              
60             # Compute a directory name that will be used to know
61             # if the file must be purge. We don't want a new directory
62             # everytime, so we use a 10h frame
63 4         18 $filePath .= int(time/10000)*10000 + ($self->{retention_duration} * 60);
64 4         9 $filePath .= '/'.$subFilePath;
65              
66 4         34 return $filePath;
67             }
68              
69             sub download {
70 0     0 0 0 my ($self) = @_;
71              
72 0 0       0 die unless $self->{mirrors};
73              
74 0         0 my $mirrorList = $self->{mirrors};
75              
76              
77 0         0 my $p2pHostList;
78              
79 0         0 MULTIPART: foreach my $sha512 (@{$self->{multiparts}}) {
  0         0  
80 0         0 my $partFilePath = $self->getPartFilePath($sha512);
81 0         0 File::Path::mkpath(dirname($partFilePath));
82 0 0       0 if (-f $partFilePath) {
83 0 0       0 next MULTIPART if $self->_getSha512ByFile($partFilePath) eq $sha512;
84             }
85              
86 0         0 eval {
87 0 0 0     0 if ($self->{p2p} && (ref($p2pHostList) ne 'ARRAY') && FusionInventory::Agent::Task::Deploy::P2P->require) {
      0        
88 0         0 $p2pHostList = FusionInventory::Agent::Task::Deploy::P2P::findPeer(62354, $self->{logger});
89             }
90             };
91 0 0       0 $self->{logger}->debug("failed to enable P2P: $@") if $@;
92              
93              
94 0         0 my $lastGood;
95 0         0 my %remote = (p2p => $p2pHostList, mirror => $mirrorList);
96 0         0 foreach my $remoteType (qw/p2p mirror/) {
97 0         0 foreach my $mirror ($lastGood, @{$remote{$remoteType}}) {
  0         0  
98 0 0       0 next unless $mirror;
99              
100 0 0       0 next unless $sha512 =~ /^(.)(.)/;
101 0         0 my $sha512dir = $1.'/'.$1.$2.'/';
102              
103 0         0 $self->{logger}->debug($mirror.$sha512dir.$sha512);
104              
105 0         0 my $request = HTTP::Request->new(GET => $mirror.$sha512dir.$sha512);
106 0         0 my $response = $self->{client}->request($request, $partFilePath);
107              
108 0 0 0     0 if ($response && ($response->code == 200) && -f $partFilePath) {
      0        
109 0 0       0 if ($self->_getSha512ByFile($partFilePath) eq $sha512) {
110 0 0       0 $lastGood = $mirror if $remoteType eq 'p2p';
111 0         0 next MULTIPART;
112             }
113 0         0 $self->{logger}->debug("sha512 failure: $sha512");
114             }
115             # bad file, drop it
116 0         0 unlink($partFilePath);
117             }
118             }
119             }
120              
121             }
122              
123             sub filePartsExists {
124 2     2 0 560 my ($self) = @_;
125              
126 2         4 foreach my $sha512 (@{$self->{multiparts}}) {
  2         7  
127              
128 2         5 my $filePath = $self->getPartFilePath($sha512);
129 2 100       39 return 0 unless -f $filePath;
130              
131             }
132 1         6 return 1;
133             }
134              
135             sub _getSha512ByFile {
136 0     0     my ($self, $filePath) = @_;
137              
138 0           my $sha = Digest::SHA->new('512');
139              
140 0           my $sha512;
141 0           eval {
142 0           $sha->addfile($filePath, 'b');
143 0           $sha512 = $sha->hexdigest;
144             };
145 0 0         $self->{logger}->debug("SHA512 failure: $@") if $@;
146              
147 0           return $sha512;
148             }
149              
150             sub validateFileByPath {
151 0     0 0   my ($self, $filePath) = @_;
152              
153              
154 0 0         if (-f $filePath) {
155 0 0         if ($self->_getSha512ByFile($filePath) eq $self->{sha512}) {
156 0           return 1;
157             }
158             }
159              
160 0           return 0;
161             }
162              
163              
164             1;