1# cluster-webmin-lib.pl 2# Common functions for managing webmin installs across a cluster 3 4BEGIN { push(@INC, ".."); }; 5use WebminCore; 6&init_config(); 7&foreign_require("servers", "servers-lib.pl"); 8 9# list_webmin_hosts() 10# Returns a list of all hosts whose webmin modules are being managed 11sub list_webmin_hosts 12{ 13local %smap = map { $_->{'id'}, $_ } &list_servers(); 14local $hdir = "$module_config_directory/hosts"; 15opendir(DIR, $hdir); 16local ($h, @rv); 17foreach $h (readdir(DIR)) { 18 next if ($h eq "." || $h eq ".." || !-d "$hdir/$h"); 19 local %host = ( 'id', $h ); 20 next if (!$smap{$h}); # underlying server was deleted 21 local $f; 22 opendir(MDIR, "$hdir/$h"); 23 foreach $f (readdir(MDIR)) { 24 if ($f =~ /^(\S+)\.mod$/) { 25 local %mod; 26 &read_file("$hdir/$h/$f", \%mod); 27 push(@{$host{'modules'}}, \%mod); 28 } 29 elsif ($f =~ /^(\S+)\.theme$/) { 30 local %theme; 31 &read_file("$hdir/$h/$f", \%theme); 32 push(@{$host{'themes'}}, \%theme); 33 } 34 elsif ($f =~ /^(\S+)\.user$/) { 35 local %user; 36 &read_file("$hdir/$h/$f", \%user); 37 $user{'modules'} = [ split(/\s+/, $user{'modules'}) ]; 38 $user{'ownmods'} = [ split(/\s+/, $user{'ownmods'}) ]; 39 $user{'olds'} = [ split(/\s+/, $user{'olds'}) ]; 40 push(@{$host{'users'}}, \%user); 41 } 42 elsif ($f =~ /^(\S+)\.group$/) { 43 local %group; 44 &read_file("$hdir/$h/$f", \%group); 45 $group{'modules'} = [ split(/\s+/, $group{'modules'}) ]; 46 $group{'ownmods'} = [ split(/\s+/, $group{'ownmods'}) ]; 47 $group{'members'} = [ split(/\s+/, $group{'members'}) ]; 48 push(@{$host{'groups'}}, \%group); 49 } 50 elsif ($f eq "webmin") { 51 &read_file("$hdir/$h/$f", \%host); 52 } 53 } 54 closedir(MDIR); 55 push(@rv, \%host); 56 } 57closedir(DIR); 58return @rv; 59} 60 61# save_webmin_host(&host) 62sub save_webmin_host 63{ 64local $hdir = "$module_config_directory/hosts"; 65local %oldfile; 66mkdir($hdir, 0700); 67if (-d "$hdir/$_[0]->{'id'}") { 68 opendir(DIR, "$hdir/$_[0]->{'id'}"); 69 map { $oldfile{$_}++ } readdir(DIR); 70 closedir(DIR); 71 } 72else { 73 mkdir("$hdir/$_[0]->{'id'}", 0700); 74 } 75local $m; 76foreach $m (@{$_[0]->{'modules'}}) { 77 &write_file("$hdir/$_[0]->{'id'}/$m->{'dir'}.mod", $m); 78 delete($oldfile{"$m->{'dir'}.mod"}); 79 } 80foreach $m (@{$_[0]->{'themes'}}) { 81 &write_file("$hdir/$_[0]->{'id'}/$m->{'dir'}.theme", $m); 82 delete($oldfile{"$m->{'dir'}.theme"}); 83 } 84foreach $m (@{$_[0]->{'users'}}) { 85 local %u = %$m; 86 $u{'modules'} = join(" ", @{$u{'modules'}}); 87 $u{'ownmods'} = join(" ", @{$u{'ownmods'}}); 88 $u{'olds'} = join(" ", @{$u{'olds'}}); 89 &write_file("$hdir/$_[0]->{'id'}/$u{'name'}.user", \%u); 90 delete($oldfile{"$u{'name'}.user"}); 91 } 92foreach $m (@{$_[0]->{'groups'}}) { 93 local %g = %$m; 94 $g{'modules'} = join(" ", @{$g{'modules'}}); 95 $g{'ownmods'} = join(" ", @{$g{'ownmods'}}); 96 $g{'members'} = join(" ", @{$g{'members'}}); 97 &write_file("$hdir/$_[0]->{'id'}/$g{'name'}.group", \%g); 98 delete($oldfile{"$g{'name'}.group"}); 99 } 100local %webmin = %{$_[0]}; 101delete($webmin{'modules'}); 102delete($webmin{'themes'}); 103delete($webmin{'users'}); 104delete($webmin{'groups'}); 105delete($webmin{'id'}); 106&write_file("$hdir/$_[0]->{'id'}/webmin", \%webmin); 107delete($oldfile{"webmin"}); 108unlink(map { "$hdir/$_[0]->{'id'}/$_" } keys %oldfile); 109} 110 111# delete_webmin_host(&host) 112sub delete_webmin_host 113{ 114system("rm -rf '$module_config_directory/hosts/$_[0]->{'id'}'"); 115} 116 117# list_servers() 118# Returns a list of all servers from the webmin servers module that can be 119# managed, plus this server 120sub list_servers 121{ 122local @servers = &servers::list_servers_sorted(); 123return ( &servers::this_server(), grep { $_->{'user'} } @servers ); 124} 125 126# server_name(&server) 127sub server_name 128{ 129return ($_[0]->{'id'} == 0 ? &get_system_hostname() : $_[0]->{'host'}). 130 ($_[0]->{'desc'} ? " (".$_[0]->{'desc'}.")" : ""); 131} 132 133# all_modules(&hosts) 134sub all_modules 135{ 136local (%done, $u, %descc); 137local @uniq = grep { !$done{$_->{'dir'}}++ } map { @{$_->{'modules'}} } @{$_[0]}; 138map { $descc{$_->{'desc'}}++ } @uniq; 139foreach $u (@uniq) { 140 $u->{'desc'} .= " ($u->{'dir'})" if ($descc{$u->{'desc'}} > 1); 141 } 142return sort { $a->{'desc'} cmp $b->{'desc'} } @uniq; 143} 144 145# all_themes(&hosts) 146sub all_themes 147{ 148local %done; 149return sort { $a->{'desc'} cmp $b->{'desc'} } 150 grep { !$done{$_->{'dir'}}++ } 151 map { @{$_->{'themes'}} } @{$_[0]}; 152} 153 154# all_groups(&hosts) 155sub all_groups 156{ 157local %done; 158return sort { $a->{'name'} cmp $b->{'name'} } 159 grep { !$done{$_->{'name'}}++ } 160 map { @{$_->{'groups'}} } @{$_[0]}; 161} 162 163# all_users(&hosts) 164sub all_users 165{ 166local %done; 167return sort { $a->{'name'} cmp $b->{'name'} } 168 grep { !$done{$_->{'name'}}++ } 169 map { @{$_->{'users'}} } @{$_[0]}; 170} 171 172# create_on_input(desc, [no-donthave], [no-have], [multiple], [colspan]) 173sub create_on_input 174{ 175local @hosts = &list_webmin_hosts(); 176local @servers = &list_servers(); 177if ($_[0]) { 178 print "<tr> <td><b>$_[0]</b></td>\n"; 179 my $colspan = "colspan=$_[4]" if ($_[4]); 180 print "<td $colspan>\n"; 181 } 182if ($_[3]) { 183 print "<select name=server size=5 multiple>\n"; 184 } 185else { 186 print "<select name=server>\n"; 187 } 188print "<option value=-1>$text{'user_all'}</option>\n"; 189print "<option value=-2>$text{'user_donthave'}</option>\n" if (!$_[1]); 190print "<option value=-3>$text{'user_have'}</option>\n" if (!$_[2]); 191local @groups = &servers::list_all_groups(\@servers); 192local $h; 193foreach $h (@hosts) { 194 local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers; 195 if ($s) { 196 print "<option value='$s->{'id'}'>", 197 $s->{'desc'} ? $s->{'desc'} : $s->{'host'},"</option>\n"; 198 $gothost{$s->{'host'}}++; 199 } 200 } 201local $g; 202foreach $g (@groups) { 203 local ($found, $m); 204 foreach $m (@{$g->{'members'}}) { 205 ($found++, last) if ($gothost{$m}); 206 } 207 print "<option value='group_$g->{'name'}'>", 208 &text('user_ofgroup', $g->{'name'}),"</option>\n" if ($found); 209 } 210print "</select>\n"; 211if ($_[0]) { 212 print "</td> </tr>\n"; 213 } 214} 215 216# create_on_parse(prefix, &already, name, [no-print]) 217sub create_on_parse 218{ 219local @allhosts = &list_webmin_hosts(); 220local @servers = &list_servers(); 221local @hosts; 222local $server; 223foreach $server (split(/\0/, $in{'server'})) { 224 if ($server == -2) { 225 # Install on hosts that don't have it 226 local %already = map { $_->{'id'}, 1 } @{$_[1]}; 227 push(@hosts, grep { !$already{$_->{'id'}} } @allhosts); 228 print "<b>",&text($_[0].'3', $_[2]),"</b><p>\n" if (!$_[3]); 229 } 230 elsif ($server == -3) { 231 # Install on hosts that do have it 232 local %already = map { $_->{'id'}, 1 } @{$_[1]}; 233 push(@hosts, grep { $already{$_->{'id'}} } @allhosts); 234 print "<b>",&text($_[0].'6', $_[2]),"</b><p>\n" if (!$_[3]); 235 } 236 elsif ($server =~ /^group_(.*)/) { 237 # Install on members of some group 238 local ($group) = grep { $_->{'name'} eq $1 } 239 &servers::list_all_groups(\@servers); 240 push(@hosts, grep { local $hid = $_->{'id'}; 241 local ($s) = grep { $_->{'id'} == $hid } @servers; 242 &indexof($s->{'host'}, @{$group->{'members'}}) >= 0 } 243 @allhosts); 244 print "<b>",&text($_[0].'4', $_[2], $group->{'name'}), 245 "</b><p>\n" if (!$_[3]); 246 } 247 elsif ($server != -1) { 248 # Just install on one host 249 local ($onehost) = grep { $_->{'id'} == $server } 250 @allhosts; 251 push(@hosts, $onehost); 252 local ($s) = grep { $_->{'id'} == $onehost->{'id'} } @servers; 253 print "<b>",&text($_[0].'5', $_[2], 254 &server_name($s)),"</b><p>\n" if (!$_[3]); 255 } 256 else { 257 # Installing on every host 258 push(@hosts, @allhosts); 259 print "<b>",&text($_[0], join(" ", @names)), 260 "</b><p>\n" if (!$_[3]); 261 } 262 } 263return &unique(@hosts); 264} 265 2661; 267 268