8ec1bc1c313190fb8ba8c895010befbf17651a43
[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->{'afsbosconfigdir'}/BosConfig"));
588     unwind($os->command('fileserver-stop'));
589 }
590 sleep(10); # allow bosserver some time to start accepting connections...
591
592 #-----------------------------------------------------------------------------
593 # Defining Cell Name and Membership for Server Processes
594 #
595 run("$bos setcellname $server $cellname -noauth");
596 run("$bos addhost $server $server -noauth");
597 run("$bos adduser $server $username -noauth");
598 if ($unwind) {
599     unwind("$bos removeuser $server $username -noauth");
600 }
601
602 # WORKAROUND:
603 # The initial bosserver startup may create CellServDB entry which does
604 # not match the host name retured by gethostbyaddr(). This entry will
605 # cause ptserver/vlserver quorum errors and so is removed.
606 open(HOSTS, "$bos listhosts $server |") or 
607   die "error: failed to run bos listhosts, $?\n";
608 my @hosts = <HOSTS>;
609 close HOSTS;
610 foreach (@hosts) {
611   chomp;
612   if (/^\s+Host \d+ is (.*)/) {
613     my $host = $1;
614     print "debug: bos listhosts: host=[$host]\n" if $debug; 
615     if ($host ne $name_from_ip) {
616       print "debug: removing invalid host '$host' from CellServDB.\n" if $debug;
617       run("$bos removehost $server $host -noauth");
618     }
619   }
620 }
621
622 #-----------------------------------------------------------------------------
623 # Starting the Database Server Processes
624 #
625 print "debug: Starting the ptserver and vlserver...\n" if $debug;
626 run("$bos create $server ptserver simple -cmd \"$path->{'afssrvlibexecdir'}/ptserver $options_ptserver\" -noauth"); 
627 if ($unwind) {
628     unwind($os->command('remove', "$path->{'afsdbdir'}/prdb.DB0"));
629     unwind($os->command('remove', "$path->{'afsdbdir'}/prdb.DBSYS1"));
630     unwind("$bos delete $server ptserver -noauth");
631     unwind("$bos stop $server ptserver -noauth");
632 }
633
634 run("$bos create $server vlserver simple -cmd \"$path->{'afssrvlibexecdir'}/vlserver $options_vlserver\" -noauth");
635 if ($unwind) {
636     unwind($os->command('remove', "$path->{'afsdbdir'}/vldb.DB0"));
637     unwind($os->command('remove', "$path->{'afsdbdir'}/vldb.DBSYS1"));
638     unwind("$bos delete $server vlserver -noauth");
639     unwind("$bos stop $server vlserver -noauth");
640 }
641
642 if ($kerberos_type =~ /kaserver/i) {
643   print "warning: kaserver is deprecated!\n";
644   run("$bos create $server kaserver simple -cmd \"$path->{'afssrvlibexecdir'}/kaserver $options_vlserver\" -noauth");
645   if ($unwind) {
646     unwind($os->command('remove', "$path->{'afsdbdir'}/kaserver.DB0"));
647     unwind($os->command('remove', "$path->{'afsdbdir'}/kaserver.DBSYS1"));
648     unwind("$bos delete $server kaserver -noauth");
649     unwind("$bos stop $server kaserver -noauth");
650   }
651 }
652
653 sleep(10); # to allow the database servers to start servicing requests.
654
655 #-----------------------------------------------------------------------------
656 # Initializing Cell Security
657 #
658 # Create the AFS administrative account and the AFS server encryption key.
659 # Make the krb.conf file if the realm name is different than the cell name.
660
661 $auth->make_krb_config();
662 $auth->make_keyfile();
663 unless ( -f "$path->{'afsconfdir'}/KeyFile") {
664   die "Failed to create $path->{'afsconfdir'}/KeyFile. Please create this using asetkey or the bos addkey command.\n";
665 }
666
667 print "debug: Creating admin user...\n" if $debug;
668 run("$pts createuser -name $username -cell $cellname -noauth");
669 run("$pts adduser $username system:administrators -cell $cellname -noauth");
670 run("$pts membership $username -cell $cellname -noauth");
671
672 print "debug: Restarting the database servers to use the new encryption key.\n" if $debug;
673 run("$bos restart $server -all -noauth");
674 sleep(10); # to allow the database servers to start servicing requests.
675
676 #-----------------------------------------------------------------------------
677 # Starting the File Server, Volume Server, and Salvager
678 #
679 print "debug: Starting the fileserver...\n" if $debug;
680 if ($with_dafs) {
681   run( "$bos create $server dafs dafs ".
682        "-cmd \"$path->{'afssrvlibexecdir'}/fileserver $options_fileserver\" ".
683        "-cmd \"$path->{'afssrvlibexecdir'}/volserver $options_volserver\"".
684        "-cmd \"$path->{'afssrvlibexecdir'}/salvageserver $options_salvageserver\" ".
685        "-cmd \"$path->{'afssrvlibexecdir'}/salvager $options_salvager\" ".
686        "-noauth");
687   if ($unwind) {
688     unwind("$bos delete $server dafs -noauth");
689     unwind("$bos stop $server dafs -noauth");
690   }
691 }
692 else {
693   run( "$bos create $server fs fs ".
694        "-cmd \"$path->{'afssrvlibexecdir'}/fileserver $options_fileserver\" ".
695        "-cmd \"$path->{'afssrvlibexecdir'}/volserver $options_volserver\" ".
696        "-cmd \"$path->{'afssrvlibexecdir'}/salvager $options_salvager\" ".
697        "-noauth");
698   if ($unwind) {
699     unwind("$bos delete $server fs -noauth");
700     unwind("$bos stop $server fs -noauth");
701   }
702 }
703
704 # Create the root.afs volume.
705 print "debug: Creating root.afs volume...\n" if $debug;
706 run("$vos create $server $partition root.afs -cell $cellname -noauth");
707 if ($unwind) {
708     unwind($os->command('remove', "$partition/AFSIDat "));
709     unwind($os->command('remove', "$partition/V*.vol"));
710     unwind($os->command('remove', "$partition/Lock"));
711     unwind("$vos remove $server $partition root.afs -cell $cellname -localauth");
712 }
713
714 #-----------------------------------------------------------------------------
715 # Installing Client Functionality
716 #
717 print "debug: Starting the OpenAFS client...\n" if $debug;
718 run($os->command('client-start'));
719 if ($unwind) {
720     unwind($os->command('client-stop'));
721 }
722
723 # Run as the administrator.
724 $auth->authorize();
725
726 #-----------------------------------------------------------------------------
727 # Configuring the Top Levels of the AFS Filespace
728 #
729 print "debug: Creating the volumes...\n" if $debug;
730 run("$fs setacl /afs system:anyuser rl");
731
732 run("$vos create $server $partition root.cell");
733 if ($unwind) {
734     unwind("$vos remove $server $partition root.cell -localauth");
735 }
736
737 run("$fs mkmount /afs/$cellname root.cell -cell $cellname -fast");
738 if ($unwind) {
739     unwind("$fs rmmount /afs/$cellname");
740 }
741
742 run("$fs setacl /afs/$cellname system:anyuser rl");
743 run("$fs mkmount /afs/.$cellname root.cell -cell $cellname -rw");
744 if ($unwind) {
745     unwind("$fs rmmount /afs/.$cellname");
746 }
747
748 run("$fs examine /afs");
749 run("$fs examine /afs/$cellname");
750
751 run("$vos addsite $server $partition root.afs");
752 run("$vos addsite $server $partition root.cell");
753 run("$vos release root.cell");
754 run("$vos release root.afs");
755
756 run("$fs checkvolumes"); # so client notices the releases
757 print "debug: the following should show root.afs.readonly\n" if $debug;
758 run("$fs examine /afs");
759 print "debug: the following should show root.cell.readonly\n" if $debug;
760 run("$fs examine /afs/$cellname");
761 print "debug: the following should show root.cell\n" if $debug;
762 run("$fs examine /afs/.$cellname");
763
764 # Create some volumes in our new cell.
765 print "debug: Creating the test volumes...\n" if $debug;
766 mkvol("user",    "/afs/.$cellname/user",         $server, $partition);
767 mkvol("service", "/afs/.$cellname/service",      $server, $partition);
768 mkvol("unrep",   "/afs/.$cellname/unreplicated", $server, $partition);
769 mkvol("rep",     "/afs/.$cellname/replicated",   $server, $partition);
770
771 run("$vos addsite $server $partition rep");
772 if ($unwind) {
773     unwind("$vos remsite $server $partition rep");
774 }
775 run("$vos release rep");
776 run("$fs mkmount /afs/.$cellname/.replicated rep -rw");
777 run("$fs setacl  /afs/.$cellname/.replicated system:anyuser rl");
778
779 # Show the new volumes in the read-only path.
780 run("$vos release root.cell"); 
781
782 # done.
783 @unwinds = (); # clear unwinds
784 print "info: DONE\n";
785
786 END {
787   if ($unwind && scalar @unwinds) {
788     print "\ninfo: Error encountered, unwinding...\n"; 
789     while (@unwinds) {
790       eval { 
791         run(pop(@unwinds));
792       };
793       if ($@) {
794         print "warn: Unwind command failed.\n$@\n"; 
795       }
796     }
797   }
798 }