606bc005df02bc3ba1ca147fc3c045681db51e4a
[openafs.git] / src / tests / afs-newcell.pl
1 #!/usr/bin/env perl
2 # Copyright (C) 2000 by Sam Hartman
3 # This file may be copied either under the terms of the GNU GPL or the IBM Public License
4 # either version 2 or later of the GPL or version 1.0 or later of the IPL.
5
6 use warnings;
7 use strict;
8 use Term::ReadLine;
9 use OpenAFS::ConfigUtils;
10 use OpenAFS::Dirpath;
11 use OpenAFS::OS;
12 use OpenAFS::Auth;
13 use Getopt::Long;
14 use Pod::Usage;
15 use Socket;
16
17 =head1  NAME
18
19    afs-newcell - Set up the initial database and file server for a new OpenAFS cell.
20
21 =head1 SYNOPSIS
22
23 B<afs-newcell>
24        [ B<--batch> ]
25        [ B<--debug> ]
26        [ B<--unwind> ]
27        [ B<--help> ]
28        [ B<--server>=hostname ]
29        [ B<--cellname>=cell ]
30        [ B<--partition>=partition ]
31        [ B<--admin>=administrator ]
32        [ B<--kerberos-type>=authentication_type ]
33        [ B<--kerberos-realm>=realm_name ]
34        [ B<--kerberos-keytab>=keytab_file ]
35        [ B<--with-dafs> ]
36        [ B<--options-ptserver>=options ]
37        [ B<--options-vlserver>=options ]
38        [ B<--options-fileserver>=options ]
39        [ B<--options-volserver>=options ] 
40        [ B<--options-salvageserver>=options ]
41        [ B<--options-salvager>=options ]
42
43 =head1 DESCRIPTION
44
45 This script sets up the initial AFS database and configures the first
46 database/file server. It also sets up an AFS cell's root volumes.  The
47 fileserver and database server binaries must already be installed.  The
48 fileserver should have an empty root.afs. This script creates root.cell, user,
49 service and populates root.afs.  
50
51 The B<batch> option specifies that the initial requirements have been met and
52 that the script can proceed without displaying the initial banner or asking for
53 confirmation.
54
55 The B<admin> option specifies the name of the administrative user.
56 This user will be given system:administrators and susers permission in
57 the cell.
58
59 The B<cellname> option specifies the name of the cell.
60
61 The B<partition> option specifies the partition letter of the AFS partition. The
62 default value is 'a', for /vicepa.
63
64 =head1 PREREQUISITES
65
66 The following requirements must be met before running
67 this script.
68
69 This machine must have a working, empty filesystem mounted on /vicepa. A
70 different partition letter may be specified by the partition command line
71 option. For example, to use /vicepb, specify '--partition=b' on the command
72 line.
73
74 The OpenAFS client and server binaries must be installed on this machine. 
75
76 A working Kerberos realm with Kerberos4 support must be available. Supported
77 Kerberos implementations are Heimdal with Kth-kerberos compatibility, MIT
78 Kerberos5, and Kaserver (deprecated).  
79
80 Create the single-DES AFS key and write it to a keytab file using the kerberos
81 kadmin program.
82    
83 Create a principal called afs/cellname in your realm.  The cell name should be
84 all lower case, unlike Kerberos realms which are all upper case.  You can use
85 the asetkey command or if you used AFS3 salt to create the key, the bos addkey
86 command. The asetkey command is built when OpenAFS built with Kerberos support.
87 The asetkey command requires a cell configuration.
88
89 You will need an administrative principal created in a Kerberos realm.  This
90 principal will be added to system:administrators and thus will be able to run
91 administrative commands.  Generally the user is a root instance of some
92 administrative user.  For example if jruser is an administrator then it would be
93 reasonable to create jruser/root and specify jruser/root as the user to be
94 added in this script using the 'admin' command line option.  You will also need
95 to create a keyfile for this adminstrative user which is used by the script to
96 obtain a ticket. The keyfile must be located in
97 $openafsdirpath->{'afsconfdir'}/krb5.conf.
98
99 The AFS client must not be running on this workstation.  It will be started
100 during the execution of this script.
101
102 =head1 AUTHOR
103
104 Sam Hartman <hartmans@debian.org>
105
106 =cut
107
108
109 my $term = new Term::ReadLine('afs-newcell');
110 my $path = $OpenAFS::Dirpath::openafsdirpath;
111
112 #-----------------------------------------------------------------------------------
113 # prompt(message, default_value)
114 #
115 sub prompt($$) {
116   my ($message,$default) = @_;
117   my $value = $term->readline("$message [$default] ");
118   unless ($value) {
119     $value = $default;
120   }
121   return $value;
122 }
123
124 #-----------------------------------------------------------------------------------
125 # mkvol(volume, mount, partition)
126 #
127 sub mkvol($$$$) {
128     my ($vol, $mnt, $srv, $part) = @_;
129     run("$path->{'afssrvsbindir'}/vos create $srv $part $vol -maxquota 0");
130     unwind("$path->{'afssrvsbindir'}/vos remove $srv $part $vol");
131     run("$path->{'afssrvbindir'}/fs mkmount $mnt $vol ");
132     run("$path->{'afssrvbindir'}/fs setacl $mnt system:anyuser rl");
133 }
134
135 #-----------------------------------------------------------------------------------
136 # check_program($prog) - verify the program is installed.
137 #
138 sub check_program($) {
139   my ($program) = @_;
140   unless ( -f $program ) {
141      die "error: Missing program: $program\n";
142   }
143   unless ( -x $program ) {
144      die "error: Not executable: $program\n";
145   }
146 }
147
148 #-----------------------------------------------------------------------------------
149 # main script
150
151 # options
152 my $batch = 0;
153 my $debug = 0;
154 my $unwind = 1;
155 my $help = 0;
156 my $cellname = 'testcell';
157 my $partition = 'a';
158 my $admin = 'admin';
159 my $kerberos_type = 'MIT';
160 my $kerberos_realm = 'TESTCELL';
161 my $kerberos_keytab = "$path->{'afsconfdir'}/krb5.keytab";
162 my $with_dafs = 0;
163 my $options_ptserver = '';
164 my $options_vlserver = '';
165 my $options_fileserver = '';
166 my $options_volserver = '';
167 my $options_salvageserver = '';
168 my $options_salvager = '';
169
170 my $server = `hostname -f`;
171 chomp $server;
172
173 GetOptions (
174        "batch!" => \$batch, 
175        "debug!" => \$debug,
176        "unwind!" => \$unwind,
177        "help" => \$help,
178        "server=s" => \$server,
179        "cellname=s" => \$cellname, 
180        "partition=s" => \$partition,
181        "admin=s" => \$admin,
182        "kerberos-type=s" => \$kerberos_type,
183        "kerberos-realm=s" => \$kerberos_realm,
184        "kerberos-keytab=s" => \$kerberos_keytab,
185        "with-dafs" => \$with_dafs,
186        "options-ptserver=s" => \$options_ptserver,
187        "options-vlserver=s" => \$options_vlserver,
188        "options-fileserver=s" => \$options_fileserver,
189        "options-volserver=s" => \$options_volserver,
190        "options-salvageserver=s" => \$options_salvageserver,
191        "options-salvager=s" => \$options_salvager,
192        );
193
194 if ($help) {
195   pod2usage(1);
196   exit 0;
197 }
198
199 # To print debug messages in the run() calls.
200 $OpenAFS::ConfigUtils::debug = $debug;
201
202 #-----------------------------------------------------------------------------
203 # Prereq: Must be root and must not already have a cell configuration.
204 #
205 my @problems = ();
206 my $try_rm_cell = 0;
207
208 if ($> != 0) {
209   push(@problems, "You must be root to run this script.");
210 }
211
212 my @afsconfigfiles = (
213   "$path->{'afsconfdir'}/ThisCell",
214   "$path->{'afsconfdir'}/CellServDB",
215   "$path->{'afsconfdir'}/UserList",
216   "$path->{'afsdbdir'}/prdb.DB0",
217   "$path->{'afsbosconfigdir'}/BosConfig",
218   "$path->{'afsddir'}/ThisCell",
219   "$path->{'afsddir'}/CellServDB",
220 );
221 foreach my $configfile (@afsconfigfiles) {
222   if ( -f $configfile ) {
223     push(@problems, "Configuration file already exists, $configfile.");
224     $try_rm_cell = 1;
225   }
226 }
227
228 if (@problems) {
229   foreach my $problem (@problems) {
230     print "error: $problem\n";
231   }
232   print "info: Try running afs-rmcell.pl\n" if $try_rm_cell;
233   exit 1;
234 }
235
236 #-----------------------------------------------------------------------------
237 # Prereq: System requirements notification.
238 #
239 unless ($batch) {
240
241   print <<eoreqs;
242                            REQUIREMENTS
243
244 The following requirements must be meet before running
245 this script. See 'pod2text $0' for more details.
246
247 1) A filesystem must be mounted on /vicepa. (See
248    the --partition option for alternative mount points.)
249
250 2) The OpenAFS client and server binaries must be installed.
251    There should be no remnants from a previous cell. 
252    Run afs-rmcell to remove any.
253
254 3) A Kerberos realm with Kerberos 4 support must be available.
255    Supported Kerberos implementations are Heimdal with
256    Kth-kerberos compatibility, MIT Kerberos 5, and 
257    Kaserver (deprecated). 
258
259 4) A Kerberos keytab file containing the afs principal 
260    and the administrator principal must be be present.
261    See the asetkey man page for information about creating the
262    keytab file.  The default name of the administrator 
263    principal is 'admin'. See the --admin option for
264    alternative names.
265
266 eoreqs
267
268   my $answer = prompt("Does your system meet these requirements? (yes/no)", "no");
269   unless ($answer=~/^y/i ) {
270     print "OK: Aborted.\n";
271     exit 0;
272   }
273 }
274
275 #-----------------------------------------------------------------------------
276 # Prereq: Verify required binaries, directories, and permissions.
277 #
278 my $bosserver = "$path->{'afssrvsbindir'}/bosserver";
279 my $bos       = "$path->{'afssrvbindir'}/bos";
280 my $fs        = "$path->{'afssrvbindir'}/fs";
281 my $pts       = "$path->{'afssrvbindir'}/pts";
282 my $vos       = "$path->{'afssrvsbindir'}/vos";
283 my $afsrc     = "$path->{'initdir'}/afs.rc";
284 my $aklog     = "$path->{'afswsbindir'}/aklog";
285 my $tokens    = "$path->{'afswsbindir'}/tokens";
286 my $klog      = "$path->{'afswsbindir'}/klog";
287 my $kas       = "$path->{'afssrvsbindir'}/kas";
288
289 check_program($bosserver);
290 check_program($bos);
291 check_program($fs);
292 check_program($pts);
293 check_program($vos);
294 check_program($afsrc);
295 check_program($tokens);
296
297 #-----------------------------------------------------------------------------
298 # Prereq: Cell configuration
299 #
300 if ($batch) {
301   if ($kerberos_type!~/kaserver/i) {
302     check_program($aklog);
303     unless ( -f $kerberos_keytab ) {
304       die "error: Missing keytab file: $kerberos_keytab\n";
305     }
306   }
307 }
308 else {
309   my $answer;
310   get_options: {
311     $answer = prompt("Print afs-newcell debugging messages? (yes/no)", $debug ? "yes" : "no");
312     $debug = ($answer=~/^y/i) ? 1 : 0;
313
314     print "\nServer options:\n"; 
315     $server = prompt("What server name should be used?", $server);
316     $cellname = prompt("What cellname should be used?", $cellname);
317     $partition = prompt("What vice partition?", $partition);
318     $admin = prompt("What administrator username?", $admin);
319     if($admin =~ /@/) {
320       die "error: Please specify the username without the realm name.\n";
321     }
322   
323     print "\nKerberos options:\n";
324     $kerberos_type = prompt("Which Kerberos is to be used?", $kerberos_type);
325     if ($kerberos_type=~/kaserver/i) {
326       check_program($klog);
327       check_program($kas);
328     }
329     else {
330       check_program($aklog);
331       $kerberos_realm = $cellname;
332       $kerberos_realm =~ tr/a-z/A-Z/;
333       $kerberos_realm = prompt("What Kerberos realm?", $kerberos_realm);
334       get_keytab: {
335         $kerberos_keytab = prompt("What keytab file?", $kerberos_keytab);
336         unless ( -f $kerberos_keytab ) {
337           print "Cannot find keytab file $kerberos_keytab\n";
338           redo get_keytab;
339         }
340       }
341     }
342   
343     print "\nDatabase Server options:\n";
344     $options_ptserver = prompt("ptserver options:", $options_ptserver);
345     $options_vlserver = prompt("vlserver options:", $options_vlserver);
346
347     print "\nFileserver options:\n";
348     $answer = prompt("Use DAFS fileserver (requires DAFS build option)? (yes/no)", "no");
349     $with_dafs = ($answer=~/^y/i) ? 1 : 0;
350     $options_fileserver = prompt("fileserver options:", $options_fileserver);
351     $options_volserver = prompt("volserver options:",  $options_volserver);
352     $options_salvageserver = prompt("salvageserver options:",  $options_salvageserver);
353     $options_salvager = prompt("salvager options:", $options_salvager);
354   
355     print "\nConfirmation:\n";
356     print "Server name            : $server\n";
357     print "Cell name              : $cellname\n";
358     print "Partition              : $partition\n";
359     print "Administrator          : $admin\n";
360     print "Kerberos               : $kerberos_type\n";
361     if ($kerberos_type!~/kaserver/i) {
362       print "Realm                  : $kerberos_realm\n";
363       print "Keytab file            : $kerberos_keytab\n";
364     }
365     print "DAFS fileserver        : ", $with_dafs ? "yes" : "no", "\n";
366     print "ptserver options       : $options_ptserver\n";
367     print "vlserver options       : $options_vlserver\n";
368     print "fileserver options     : $options_fileserver\n";
369     print "volserver options      : $options_volserver\n";
370     print "salvagerserver options : $options_salvageserver\n";
371     print "salvager options       : $options_salvager\n";
372     print "\n";
373   
374     $answer = prompt("Correct? (yes/no/quit)", "yes");
375     exit(0)          if $answer=~/^q/i;
376     redo get_options if $answer!~/^y/i;
377   }
378
379   # Save the options as a shell script for the next run.
380   $answer = prompt("Save these options? (yes/no)", "yes");
381   if ($answer=~/^y/i ) {
382     my $script = '';
383     get_script_name: {
384       $script = prompt("File name for save?", "run-afs-newcell.sh");
385       last get_script_name if ! -f $script;
386
387       $answer = prompt("File $script already exists. Overwrite? (yes/no/quit)", "no");
388       exit(0)              if $answer=~/^q/i;
389       last get_script_name if $answer=~/^yes/i;
390       redo get_script_name;
391     }
392
393     my @switches = ();
394     push(@switches, "--batch"); # automatically added to the script
395     push(@switches, "--debug")                                          if $debug;
396     push(@switches, "--nounwind")                                       unless $unwind;
397     push(@switches, "--server='$server'")                               if $server;
398     push(@switches, "--cellname='$cellname'")                           if $cellname;
399     push(@switches, "--partition='$partition'")                         if $partition;
400     push(@switches, "--admin='$admin'")                                 if $admin;
401     push(@switches, "--kerberos-type='$kerberos_type'")                 if $kerberos_type;
402     push(@switches, "--kerberos-realm='$kerberos_realm'")               if $kerberos_realm;
403     push(@switches, "--kerberos-keytab='$kerberos_keytab'")             if $kerberos_keytab;
404     push(@switches, "--with-dafs")                                      if $with_dafs;
405     push(@switches, "--options-ptserver='$options_ptserver'")           if $options_ptserver;
406     push(@switches, "--options-vlserver='$options_vlserver'")           if $options_vlserver;
407     push(@switches, "--options-fileserver='$options_fileserver'")       if $options_fileserver;
408     push(@switches, "--options-volserver='$options_volserver'")         if $options_volserver;;
409     push(@switches, "--options-salvageserver='$options_salvageserver'") if $options_salvageserver;;
410     push(@switches, "--options-salvager='$options_salvager'")           if $options_salvager;
411   
412     open(SCRIPT, "> $script") or die "error: Cannot open file $script: $!\n";
413     print SCRIPT "#!/bin/sh\n";
414     print SCRIPT "perl afs-newcell.pl \\\n";
415     print SCRIPT join(" \\\n", map("  $_", @switches));
416     print SCRIPT "\n\n";
417     close SCRIPT;
418     chmod(0755, $script);
419   }
420 }
421
422 if ($debug) {
423   print "debug: afs-newcell options\n";
424   print "debug:  \$batch = '$batch'\n";
425   print "debug:  \$debug = '$debug'\n";
426   print "debug:  \$unwind = '$unwind'\n";
427   print "debug:  \$help = '$help'\n";
428   print "debug:  \$server = '$server'\n";
429   print "debug:  \$cellname = '$cellname'\n";
430   print "debug:  \$partition = '$partition'\n";
431   print "debug:  \$admin = '$admin'\n";
432   print "debug:  \$kerberos_type = '$kerberos_type'\n";
433   print "debug:  \$kerberos_realm = '$kerberos_realm'\n";
434   print "debug:  \$kerberos_keytab = '$kerberos_keytab'\n";
435   print "debug:  \$with_dafs = '$with_dafs'\n";
436   print "debug:  \$options_pteserver = '$options_ptserver'\n";
437   print "debug:  \$options_pteserver = '$options_vlserver'\n";
438   print "debug:  \$options_fileserver = '$options_fileserver'\n";
439   print "debug:  \$options_volserver = '$options_volserver'\n";
440   print "debug:  \$options_salvageserver = '$options_salvageserver'\n";
441   print "debug:  \$options_salvager = '$options_salvager'\n";
442 }
443
444
445 #-----------------------------------------------------------------------------
446 # Prereq: Sanity check the forward and reverse name resolution.
447 #
448 if ($server eq 'localhost') {
449   die "error: localhost is not a valid --server parameter. Use the ip hostname of this machine.\n";
450 }
451 my $packed_ip = gethostbyname($server);
452 unless (defined $packed_ip) {
453   die "error: gethostbyname failed, $?\n";
454 }
455 my $ip_from_name = inet_ntoa($packed_ip);
456 print "debug: $server ip address is $ip_from_name\n" if $debug;
457 if ($ip_from_name=~/^127/) {
458   die "error: Loopback address $ip_from_name cannot not be used for server $server. Check your /etc/hosts file.\n";
459 }
460
461 my $name_from_ip  = gethostbyaddr($packed_ip, AF_INET);
462 print "debug: hostname of $ip_from_name is $name_from_ip\n" if $debug;
463 if ($name_from_ip ne $server) {
464   die "error: Name from ip $name_from_ip does not match ip from name $ip_from_name for --server $server. ".
465       " Use the correct --server parameter and verify forward and reverse name resolution is working.\n";
466 }
467
468 #-----------------------------------------------------------------------------
469 # Prereq: The vice partition must be available and empty.
470 #
471 unless ($partition=~/^(([a-z])|([a-h][a-z])|([i][a-v]))$/) {
472   die "error: Invalid partition id specified: $partition. Valid values are a..z and aa..iv\n";
473 }
474 unless ( -d "/vicep$partition" ) {
475   die "error: Missing fileserver partition, /vicep$partition\n";
476 }
477 if ( -d "/vicep$partition/AFSIDat" ) {
478   die "error: Fileserver partition is not empty. /vicep$partition/AFSIDat needs to be removed.\n";
479 }
480 open(LS, "ls /vicep$partition |") or 
481   die "error: ls /vicep$partition failed, $!\n";
482 while (<LS>) {
483   chomp;
484   if (/^V\d+.vol$/) {
485     die "error: Fileserver partition, /vicep$partition, is not empty.\n";
486   }
487 }
488 close LS;
489
490 # Prereq: authorization and platform specific objects.
491 my $auth = OpenAFS::Auth::create(
492       'debug'=>$debug,
493       'type'=>$kerberos_type, 
494       'cell'=>$cellname,
495       'realm'=>$kerberos_realm,
496       'keytab'=>$kerberos_keytab,
497       'admin'=>$admin,
498       );
499
500 my $os = OpenAFS::OS::create(
501       'debug'=>$debug,
502       );
503
504 #-----------------------------------------------------------------------------
505 # Prereq: Sanity check admin username and convert kerberos 5 notation to afs.
506 #
507 if ($admin =~ /@/) {
508    die "error: Please specify the username without the realm name.\n";
509 }
510 my $username = $admin;
511 $username=~s:/:.:g;   # convert kerberos separators to afs separators.
512
513 #-----------------------------------------------------------------------------
514 # Prereq: Save the paths and setup configuration in a form that is easily
515 # read by the shell scripts.
516 #
517 open(CONF, "> dirpath.conf") or die "error: Cannot open file dirpath.conf for writing: $!\n";
518 my ($n, $v);
519 while(($n,$v)=each(%{$path})) {
520   print CONF "$n=$v\n";
521 }
522 close CONF;
523 open(CONF, "> run-tests.conf") or die "error: Cannot open file run-tests.conf for writing: $!\n";
524   print CONF <<"__CONF__";
525 CELLNAME=$cellname
526 PARTITION=$partition
527 ADMIN=$admin
528 KERBEROS_TYPE=$kerberos_type
529 KERBEROS_REALM=$kerberos_realm
530 KERBEROS_KEYTAB=$kerberos_keytab
531 __CONF__
532 close CONF;
533
534 unless ($batch) {
535   my $answer = prompt("Last chance to cancel before setup begins. Continue? (yes/no)", "yes");
536   exit(0) unless $answer=~/^y/i;
537 }
538
539 #-----------------------------------------------------------------------------
540 # Prereq: Shutdown the client and server, if running.
541 #
542 run($os->command('client-stop'));
543 run($os->command('fileserver-stop'));
544
545 #-----------------------------------------------------------------------------
546 # Prereq: Verify the server processes are not running.
547 #
548 foreach my $program ('bosserver', 'ptserver', 'vlserver', 'kaserver', 'fileserver') {
549   die "error: program is already running, $program\n" if $os->number_running($program);
550 }
551
552 #-----------------------------------------------------------------------------
553 # Perform Platform-Specific Procedures
554 $os->configure_client();
555
556 #-----------------------------------------------------------------------------
557 # WORKAROUND:
558 # bosserver attempts to create the following directories with these limited 
559 # permissions. However, bosserver does not create parent directories as needed, so
560 # the directories are not successfully created when they are more than one level
561 # deep. 
562 run("mkdir -m 0775 -p $path->{'afsconfdir'}");
563 run("mkdir -m 0700 -p $path->{'afslocaldir'}");
564 run("mkdir -m 0700 -p $path->{'afsdbdir'}");
565 run("mkdir -m 0755 -p $path->{'afslogsdir'}"); 
566 run("mkdir -m 0777 -p $path->{'viceetcdir'}");
567
568 # In case the directories were created earlier with the wrong permissions.
569 run("chmod 0775 $path->{'afsconfdir'}");
570 run("chmod 0700 $path->{'afslocaldir'}");
571 run("chmod 0700 $path->{'afsdbdir'}");
572 run("chmod 0755 $path->{'afslogsdir'}"); 
573 run("chmod 0777 $path->{'viceetcdir'}");
574
575 #-----------------------------------------------------------------------------
576 # Starting the BOS Server
577 #
578 # Start the bosserver and create the initial server configuration.
579 # Authorization is disabled by the -noauth flag.
580 #
581 print "debug: Starting bosserver...\n" if $debug;
582 run("$path->{'afssrvsbindir'}/bosserver -noauth");
583 if ($unwind) {
584     unwind($os->command('remove', "$path->{'afsconfdir'}/ThisCell"));
585     unwind($os->command('remove', "$path->{'afsconfdir'}/CellServDB"));
586     unwind($os->command('remove', "$path->{'afsconfdir'}/UserList"));
587     unwind($os->command('remove', "$path->{'afsconfdir'}/KeyFile"));
588     unwind($os->command('remove', "$path->{'afsbosconfigdir'}/BosConfig"));
589     unwind($os->command('fileserver-stop'));
590 }
591 sleep(10); # allow bosserver some time to start accepting connections...
592
593 #-----------------------------------------------------------------------------
594 # Defining Cell Name and Membership for Server Processes
595 #
596 run("$bos setcellname $server $cellname -noauth");
597 run("$bos addhost $server $server -noauth");
598 run("$bos adduser $server $username -noauth");
599 if ($unwind) {
600     unwind("$bos removeuser $server $username -noauth");
601 }
602
603 # WORKAROUND:
604 # The initial bosserver startup may create CellServDB entry which does
605 # not match the host name retured by gethostbyaddr(). This entry will
606 # cause ptserver/vlserver quorum errors and so is removed.
607 open(HOSTS, "$bos listhosts $server |") or 
608   die "error: failed to run bos listhosts, $?\n";
609 my @hosts = <HOSTS>;
610 close HOSTS;
611 foreach (@hosts) {
612   chomp;
613   if (/^\s+Host \d+ is (.*)/) {
614     my $host = $1;
615     print "debug: bos listhosts: host=[$host]\n" if $debug; 
616     if ($host ne $name_from_ip) {
617       print "debug: removing invalid host '$host' from CellServDB.\n" if $debug;
618       run("$bos removehost $server $host -noauth");
619     }
620   }
621 }
622
623 #-----------------------------------------------------------------------------
624 # Starting the Database Server Processes
625 #
626 print "debug: Starting the ptserver and vlserver...\n" if $debug;
627 run("$bos create $server ptserver simple -cmd \"$path->{'afssrvlibexecdir'}/ptserver $options_ptserver\" -noauth"); 
628 if ($unwind) {
629     unwind($os->command('remove', "$path->{'afsdbdir'}/prdb.DB0"));
630     unwind($os->command('remove', "$path->{'afsdbdir'}/prdb.DBSYS1"));
631     unwind("$bos delete $server ptserver -noauth");
632     unwind("$bos stop $server ptserver -noauth");
633 }
634
635 run("$bos create $server vlserver simple -cmd \"$path->{'afssrvlibexecdir'}/vlserver $options_vlserver\" -noauth");
636 if ($unwind) {
637     unwind($os->command('remove', "$path->{'afsdbdir'}/vldb.DB0"));
638     unwind($os->command('remove', "$path->{'afsdbdir'}/vldb.DBSYS1"));
639     unwind("$bos delete $server vlserver -noauth");
640     unwind("$bos stop $server vlserver -noauth");
641 }
642
643 if ($kerberos_type =~ /kaserver/i) {
644   print "warning: kaserver is deprecated!\n";
645   run("$bos create $server kaserver simple -cmd \"$path->{'afssrvlibexecdir'}/kaserver $options_vlserver\" -noauth");
646   if ($unwind) {
647     unwind($os->command('remove', "$path->{'afsdbdir'}/kaserver.DB0"));
648     unwind($os->command('remove', "$path->{'afsdbdir'}/kaserver.DBSYS1"));
649     unwind("$bos delete $server kaserver -noauth");
650     unwind("$bos stop $server kaserver -noauth");
651   }
652 }
653
654 sleep(10); # to allow the database servers to start servicing requests.
655
656 #-----------------------------------------------------------------------------
657 # Initializing Cell Security
658 #
659 # Create the AFS administrative account and the AFS server encryption key.
660 # Make the krb.conf file if the realm name is different than the cell name.
661
662 $auth->make_krb_config();
663 $auth->make_keyfile();
664 unless ( -f "$path->{'afsconfdir'}/KeyFile") {
665   die "Failed to create $path->{'afsconfdir'}/KeyFile. Please create this using asetkey or the bos addkey command.\n";
666 }
667
668 print "debug: Creating admin user...\n" if $debug;
669 run("$pts createuser -name $username -cell $cellname -noauth");
670 run("$pts adduser $username system:administrators -cell $cellname -noauth");
671 run("$pts membership $username -cell $cellname -noauth");
672
673 print "debug: Restarting the database servers to use the new encryption key.\n" if $debug;
674 run("$bos restart $server -all -noauth");
675 sleep(10); # to allow the database servers to start servicing requests.
676
677 #-----------------------------------------------------------------------------
678 # Starting the File Server, Volume Server, and Salvager
679 #
680 print "debug: Starting the fileserver...\n" if $debug;
681 if ($with_dafs) {
682   run( "$bos create $server dafs dafs ".
683        "-cmd \"$path->{'afssrvlibexecdir'}/fileserver $options_fileserver\" ".
684        "-cmd \"$path->{'afssrvlibexecdir'}/volserver $options_volserver\" ".
685        "-cmd \"$path->{'afssrvlibexecdir'}/salvageserver $options_salvageserver\" ".
686        "-cmd \"$path->{'afssrvlibexecdir'}/salvager $options_salvager\" ".
687        "-noauth");
688   if ($unwind) {
689     unwind("$bos delete $server dafs -noauth");
690     unwind("$bos stop $server dafs -noauth");
691   }
692 }
693 else {
694   run( "$bos create $server fs fs ".
695        "-cmd \"$path->{'afssrvlibexecdir'}/fileserver $options_fileserver\" ".
696        "-cmd \"$path->{'afssrvlibexecdir'}/volserver $options_volserver\" ".
697        "-cmd \"$path->{'afssrvlibexecdir'}/salvager $options_salvager\" ".
698        "-noauth");
699   if ($unwind) {
700     unwind("$bos delete $server fs -noauth");
701     unwind("$bos stop $server fs -noauth");
702   }
703 }
704
705 # Create the root.afs volume.
706 print "debug: Creating root.afs volume...\n" if $debug;
707 run("$vos create $server $partition root.afs -cell $cellname -noauth");
708 if ($unwind) {
709     unwind($os->command('remove', "$partition/AFSIDat "));
710     unwind($os->command('remove', "$partition/V*.vol"));
711     unwind($os->command('remove', "$partition/Lock"));
712     unwind("$vos remove $server $partition root.afs -cell $cellname -localauth");
713 }
714
715 #-----------------------------------------------------------------------------
716 # Installing Client Functionality
717 #
718 print "debug: Starting the OpenAFS client...\n" if $debug;
719 run($os->command('client-start'));
720 if ($unwind) {
721     unwind($os->command('client-stop'));
722 }
723
724 # Run as the administrator.
725 $auth->authorize();
726
727 #-----------------------------------------------------------------------------
728 # Configuring the Top Levels of the AFS Filespace
729 #
730 print "debug: Creating the volumes...\n" if $debug;
731 run("$fs setacl /afs system:anyuser rl");
732
733 run("$vos create $server $partition root.cell");
734 if ($unwind) {
735     unwind("$vos remove $server $partition root.cell -localauth");
736 }
737
738 run("$fs mkmount /afs/$cellname root.cell -cell $cellname -fast");
739 if ($unwind) {
740     unwind("$fs rmmount /afs/$cellname");
741 }
742
743 run("$fs setacl /afs/$cellname system:anyuser rl");
744 run("$fs mkmount /afs/.$cellname root.cell -cell $cellname -rw");
745 if ($unwind) {
746     unwind("$fs rmmount /afs/.$cellname");
747 }
748
749 run("$fs examine /afs");
750 run("$fs examine /afs/$cellname");
751
752 run("$vos addsite $server $partition root.afs");
753 run("$vos addsite $server $partition root.cell");
754 run("$vos release root.cell");
755 run("$vos release root.afs");
756
757 run("$fs checkvolumes"); # so client notices the releases
758 print "debug: the following should show root.afs.readonly\n" if $debug;
759 run("$fs examine /afs");
760 print "debug: the following should show root.cell.readonly\n" if $debug;
761 run("$fs examine /afs/$cellname");
762 print "debug: the following should show root.cell\n" if $debug;
763 run("$fs examine /afs/.$cellname");
764
765 # Create some volumes in our new cell.
766 print "debug: Creating the test volumes...\n" if $debug;
767 mkvol("user",    "/afs/.$cellname/user",         $server, $partition);
768 mkvol("service", "/afs/.$cellname/service",      $server, $partition);
769 mkvol("unrep",   "/afs/.$cellname/unreplicated", $server, $partition);
770 mkvol("rep",     "/afs/.$cellname/replicated",   $server, $partition);
771
772 run("$vos addsite $server $partition rep");
773 if ($unwind) {
774     unwind("$vos remsite $server $partition rep");
775 }
776 run("$vos release rep");
777 run("$fs mkmount /afs/.$cellname/.replicated rep -rw");
778 run("$fs setacl  /afs/.$cellname/.replicated system:anyuser rl");
779
780 # Show the new volumes in the read-only path.
781 run("$vos release root.cell"); 
782
783 # done.
784 @unwinds = (); # clear unwinds
785 print "info: DONE\n";
786
787 END {
788   if ($unwind && scalar @unwinds) {
789     print "\ninfo: Error encountered, unwinding...\n"; 
790     while (@unwinds) {
791       eval { 
792         run(pop(@unwinds));
793       };
794       if ($@) {
795         print "warn: Unwind command failed.\n$@\n"; 
796       }
797     }
798   }
799 }