3 # Install some package on all hosts, in parallel. If the package was
4 # downloaded from a URL, have the hosts do the same - otherwise, transfer
7 require './cluster-software-lib.pl';
10 # Work out package names, for display to use
11 @packages = $in{'source'} == 3 ? split(/\s+/, $in{'file'}) :
12 $in{'unknownfile'} ? ( $in{'unknownfile'} ) :
13 &software::file_packages($in{'file'});
14 foreach $p (@packages) {
15 local ($n, $d) = split(/\s+/, $p, 2);
17 push(@descs, $d || $n);
20 $in{'source'} == 3 || -r $in{'file'} || &error($text{'do_edeleted'});
21 &ui_print_header(undef, $text{'do_title'}, "");
23 # Setup error handler for down hosts
26 $inst_error_msg = join("", @_);
28 &remote_error_setup(\&inst_error);
30 # Work out hosts to install on
31 @hosts = &list_software_hosts();
32 @already = grep { local ($alr) = grep { $_->{'name'} eq $names[0] }
35 @hosts = &create_on_parse("do_header", \@already, join(" ", @names));
36 @servers = &list_servers();
41 local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
42 local $d = $s->{'desc'} || $s->{'realhost'} || $s->{'host'};
44 local ($rh = "READ$p", $wh = "WRITE$p");
46 select($wh); $| = 1; select(STDOUT);
48 # Do the install in a subprocess
51 &remote_foreign_require($s->{'host'}, "software",
53 if ($inst_error_msg) {
54 # Failed to contact host ..
55 print $wh &serialise_variable([ $inst_error_msg ]);
59 local $need_unlink = 1;
60 if ($in{'source'} == 3) {
61 # Installing from an update service like APT or YUM
65 # This host, so we already have the file
69 elsif ($in{'source'} == 0) {
70 # Is the file the same on remote (like if we have NFS)
71 local @st = stat($in{'file'});
72 local $rst = &remote_eval($s->{'host'}, "software",
73 "[ stat('$in{'file'}') ]");
75 if (@st && @rst && $st[7] == $rst[7] &&
77 # File is the same! No need to download
82 # Need to copy the file across :(
83 local $filename = $in{'file'};
84 $filename =~ /([^\/\\]+)$/;
85 $rfile = &remote_write(
86 $s->{'host'}, $in{'file'}, undef, "$1");
89 elsif ($in{'source'} == 2 && $in{'down'}) {
90 # Ask the remote server to download the file
91 local $filename = $in{'file'};
92 $filename =~ /([^\/\\]+$)/;
93 $rfile = &remote_foreign_call($s->{'host'}, "software",
96 &remote_foreign_call($s->{'host'}, "software",
97 "ftp_download", $in{'host'}, $in{'ftpfile'},
101 &remote_foreign_call($s->{'host'}, "software",
102 "http_download", $in{'host'}, $in{'port'},
103 $in{'page'}, $rfile, undef, undef,
108 # Need to copy the file across :(
109 local $filename = $in{'file'};
110 $filename =~ /([^\/\\]+)$/;
111 $rfile = &remote_write($s->{'host'}, $in{'file'},
117 if ($in{'source'} != 3) {
118 # Installing some package
119 for($i=0; $i<@names; $i++) {
120 local $error = &remote_foreign_call(
121 $s->{'host'}, "software",
122 "install_package", $rfile,
128 # Success .. get the package details
129 push(@rv, [ &remote_foreign_call($s->{'host'}, "software", "package_info", $names[$i]) ] );
134 # Install from update system
135 local $rus = &remote_eval($s->{'host'}, "software",
137 if ($rus ne $software::update_system) {
138 push(@rv, &text('install_erus',
139 $rus, $software::update_system));
142 local @resp = &remote_foreign_call($s->{'host'},
143 "software", "capture_function_output",
144 "update_system_install", $in{'file'});
146 # Worked .. get package details
147 foreach $p (@{$resp[1]}) {
148 push(@rv, [ &remote_foreign_call($s->{'host'}, "software", "package_info", $p) ] );
152 push(@rv, $text{'install_eupdate'});
156 &remote_eval($s->{'host'}, "software", "unlink('$rfile')")
159 print $wh &serialise_variable(\@rv);
167 # Get back all the results
169 foreach $h (@hosts) {
170 local $rh = "READ$p";
173 local $rv = &unserialise_variable($line);
175 local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
176 local $d = $s->{'desc'} || $s->{'realhost'} || $s->{'host'};
179 print &text('do_failed', $d, "Unknown reason"),"<br>\n";
186 print &text('do_success', $d),"<br>\n";
187 $pinfo[$i] = $r if (!$pinfo[$i] && @$r);
189 # Failed to get info! Need a refresh..
190 $refresh{$s->{'id'}} = 1;
192 elsif (&indexof($names[$i],
193 @{$h->{'packages'}}) < 0) {
194 push(@{$h->{'packages'}},
195 { 'name' => $names[$i],
196 'desc' => $descs[$i],
197 'class' => $pinfo[$i]->[1],
198 'version' => $pinfo[$i]->[4] });
199 &save_software_host($h);
203 # Failed for some reason..
204 print &text('do_failed', $d, $r),"<br>\n";
212 unlink($in{'file'}) if ($in{'need_unlink'});
213 print "<p><b>$text{'do_done'}</b><p>\n";
215 # Show details of installed packages, where we have them
216 for($i=0; $i<@names; $i++) {
217 next if (!$pinfo[$i]);
218 print "<table border width=100%>\n";
219 print "<tr $tb> <td><b>$text{'do_details'}</b></td> </tr>\n";
220 print "<tr $cb> <td><table width=100%>\n";
222 if ($pinfo[$i]->[2]) {
223 print "<tr> <td valign=top width=20%><b>$text{'do_desc'}</b></td>\n";
224 print "<td colspan=3><pre>$pinfo[$i]->[2]</pre></td> </tr>\n";
227 print "<tr> <td width=20%><b>$text{'do_pack'}</b></td> <td>$pinfo[$i]->[0]</td>\n";
228 print "<td width=20%><b>$text{'do_class'}</b></td> <td>",
229 $pinfo[$i]->[1] ? $pinfo[$i]->[1] : $text{'do_none'},"</td> </tr>\n";
231 print "<tr> <td width=20%><b>$text{'do_ver'}</b></td> <td>$pinfo[$i]->[4]</td>\n";
232 print "<td width=20%><b>$text{'do_vend'}</b></td> <td>$pinfo[$i]->[5]</td> </tr>\n";
234 print "<tr> <td width=20%><b>$text{'do_arch'}</b></td> <td>$pinfo[$i]->[3]</td>\n";
235 print "<td width=20%><b>$text{'do_inst'}</b></td> <td>$pinfo[$i]->[6]</td> </tr>\n";
236 print "</table></td></tr></table><p>\n";
240 &ui_print_footer("", $text{'index_return'});