Handle hostnames with upper-case letters
[webmin.git] / cluster-webmin / update.cgi
1 #!/usr/local/bin/perl
2 # update.cgi
3 # Download and install needed updates on multiple servers
4
5 require './cluster-webmin-lib.pl';
6 &foreign_require("webmin", "webmin-lib.pl");
7 &ReadParse();
8 &error_setup($webmin::text{'update_err'});
9
10 # Fetch list of updates
11 ($updates, $host, $port, $page, $ssl) = &webmin::fetch_updates(
12         $in{'source'} == 0 ? $webmin::update_url : $in{'other'});
13
14 # Build list of selected hosts, and show them
15 @servers = &list_servers();
16 &ui_print_unbuffered_header(undef, $text{'update_title'}, "");
17 @hosts = &create_on_parse("update_header", undef, undef);
18
19 # Setup error handler for down hosts
20 sub inst_error
21 {
22 $inst_error_msg = join("", @_);
23 }
24 &remote_error_setup(\&inst_error);
25
26 # Run the update, on all hosts in parallel
27 $p = 0;
28 foreach $h (@hosts) {
29         local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
30         $s || &error("Failed to find server for $h->{'id'}");
31
32         local ($rh = "READ$p", $wh = "WRITE$p");
33         pipe($rh, $wh);
34         select($wh); $| = 1; select(STDOUT);
35         if (!fork()) {
36                 # Do the install in a subprocess
37                 close($rh);
38
39                 &remote_foreign_require($s->{'host'}, "webmin",
40                                         "webmin-lib.pl");
41                 if ($inst_error_msg) {
42                         # Failed to contact host ..
43                         print $wh &serialise_variable($inst_error_msg);
44                         exit;
45                         }
46
47                 # Work out which modules are needed
48                 local @rv;
49                 local $bv = &remote_foreign_call(
50                         $s->{'host'}, "webmin",
51                         "get_webmin_base_version");
52                 foreach $u (@$updates) {
53                         local %minfo = &remote_foreign_call(
54                                 $s->{'host'}, "webmin",
55                                 "get_module_info", $u->[0]);
56                         local %tinfo = %minfo ? () :
57                                 &remote_foreign_call(
58                                         $s->{'host'}, "webmin",
59                                         "get_theme_info", $u->[0]);
60                         local %info = %minfo ? %minfo : %tinfo;
61                         next if (($u->[1] >= $bv + .01 ||
62                                   $u->[1] < $bv) &&
63                                  (!%info || $info{'longdesc'} || !$in{'third'}));
64
65                         # Check if update is appropriate
66                         $count++;
67                         if (!%info && !$in{'missing'}) {
68                                 push(@rv, &webmin::text('update_mmissing',
69                                                       "<b>$u->[0]</b>"));
70                                 next;
71                                 }
72                         if (%info && $info{'version'} >= $u->[1]) {
73                                 push(@rv, &webmin::text('update_malready',
74                                                       "<b>$u->[0]</b>"));
75                                 next;
76                                 }
77                         local $osinfo = { 'os_support' => $u->[3] };
78                         if (!&check_os_support($osinfo)) {
79                                 push(@rv, &webmin::text('update_mos',
80                                                       "<b>$u->[0]</b>"));
81                                 next;
82                                 }
83
84                         if ($in{'show'}) {
85                                 # Just send back info
86                                 push(@rv, [ 0, @$u ]);
87                                 }
88                         else {
89                                 # Do the update!
90                                 ($mhost, $mport, $mpage, $mssl) =
91                                         &parse_http_url($u->[2], $host, $port, $page, $ssl);
92                                 $mtemp = &remote_foreign_call(
93                                         $s->{'host'}, "webmin", "tempname");
94                                 local $err;
95                                 &remote_foreign_call(
96                                         $s->{'host'}, "webmin",
97                                         "http_download", $mhost, $mport,
98                                         $mpage, $mtemp, \$err, undef, $mssl);
99                                 if ($err) {
100                                         # Download failed
101                                         push(@rv, $err);
102                                         }
103                                 else {
104                                         # Do the install
105                                         $irv = &remote_foreign_call(
106                                                 $s->{'host'}, "webmin",
107                                                 "install_webmin_module",
108                                                 $mtemp, 1, 0,
109                                                 [ $base_remote_user ]);
110                                         if (ref($irv)) {
111                                                 push(@rv, [ 1, @$u ]);
112                                                 }
113                                         else {
114                                                 push(@rv, $irv);
115                                                 }
116                                         }
117                                 }
118                         }
119                 print $wh &serialise_variable(\@rv);
120                 close($wh);
121                 exit;
122                 }
123         close($wh);
124         $p++;
125         }
126
127 # Get back all the results
128 $p = 0;
129 foreach $h (@hosts) {
130         local $rh = "READ$p";
131         local $line = <$rh>;
132         close($rh);
133         local $rv = &unserialise_variable($line);
134
135         local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
136         local $d = &server_name($s);
137
138         print &text('update_onhost', $d),"<br>\n";
139         if (!$line) {
140                 print &text('update_failed', "Unknown reason"),"<p>\n";
141                 }
142         elsif (!ref($rv)) {
143                 print &text('update_failed', $rv),"<p>\n";
144                 }
145         elsif (!@$rv) {
146                 print &text('update_none', $rv),"<p>\n";
147                 }
148         else {
149                 # Show list of modules
150                 print "<ul>\n";
151                 foreach $u (@$rv) {
152                         if (ref($u)) {
153                                 # A module
154                                 print &webmin::text($u->[0] ? 'update_mok' : 'update_mshow', "<b>$u->[1]</b>", "<b>$u->[2]</b>"),"<br>\n";
155                                 print "&nbsp;&nbsp;&nbsp;$webmin::text{'update_fixes'} : $u->[5]<br>\n";
156                                 }
157                         else {
158                                 # Some message
159                                 print $u,"<br>\n";
160                                 }
161                         }
162                 print "</ul><p>\n";
163                 }
164         $p++;
165         }
166 print "<p><b>$text{'upgrade_done'}</b><p>\n";
167
168 &remote_finished();
169 &ui_print_footer("", $text{'index_return'});
170