openbsd-packaging-20060421
[openafs.git] / src / packaging / Debian / afs-newcell
1 #!/usr/bin/perl -w
2 # Copyright (C) 2000 by Sam Hartman
3 # This file may be copied either under the terms of the GNU GPL or the IBM
4 # Public License either version 2 or later of the GPL or version 1.0 or later
5 # of the IPL.
6
7 use Term::ReadLine;
8 use strict;
9 use Debian::OpenAFS::ConfigUtils;
10 use Getopt::Long;
11 use Socket qw(inet_ntoa);
12 use vars qw($admin $server $requirements_met $shutdown_needed);
13 my $rl = new Term::ReadLine('afs-newcell');
14
15 =head1  NAME
16
17 afs-newcell - Set up initial database server for AFS cell
18
19 =head1 SYNOPSIS
20
21 B<afs-newcell> [B<--requirements-met>] [B<--admin> admin_user]
22
23 =head1 DESCRIPTION
24
25 This script sets up the initial AFS database and configures the first
26 database/file server.
27
28 The B<--requirements-met> option specifies that the initial requirements have
29 been met and that the script can proceed without displaying the initial
30 banner or asking for confirmation.
31
32 The B<--admin> option specifies the name of the administrative user.  This
33 user will be given system:administrators and susers permission in the cell.
34
35 =head1 AUTHOR
36
37 Sam Hartman <hartmans@debian.org>
38
39 =cut
40
41 # Flush all output immediately.
42 $| = 1;
43
44 GetOptions ("requirements-met" => \$requirements_met, "admin=s" => \$admin);
45
46 unless ($requirements_met) {
47     print <<eoreqs;
48                             Prerequisites
49
50 In order to set up a new AFS cell, you must meet the following:
51
52 1) You need a working Kerberos realm with Kerberos4 support.  You
53    should install Heimdal with KTH Kerberos compatibility or MIT
54    Kerberos 5.
55
56 2) You need to create the single-DES AFS key and load it into
57    /etc/openafs/server/KeyFile.  If your cell's name is the same as
58    your Kerberos realm then create a principal called afs.  Otherwise,
59    create a principal called afs/cellname in your realm.  The cell
60    name should be all lower case, unlike Kerberos realms which are all
61    upper case.  You can use asetkey from the openafs-krb5 package, or
62    if you used AFS3 salt to create the key, the bos addkey command.
63
64 3) This machine should have a filesystem mounted on /vicepa.  If you
65    do not have a free partition, then create a large file by using dd
66    to extract bytes from /dev/zero.  Create a filesystem on this file
67    and mount it using -oloop.
68
69 4) You will need an administrative principal created in a Kerberos
70    realm.  This principal will be added to susers and
71    system:administrators and thus will be able to run administrative
72    commands.  Generally the user is a root or admin instance of some
73    administrative user.  For example if jruser is an administrator then
74    it would be reasonable to create jruser/admin (or jruser/root) and
75    specify that as the user to be added in this script.
76
77 5) The AFS client must not be running on this workstation.  It will be
78    at the end of this script.
79
80 eoreqs
81 #'# cperl-mode
82
83     $_ = $rl->readline("Do you meet these requirements? [y/n] ");
84     unless (/^y/i ) {
85         print "Run this script again when you meet the requirements\n";
86         exit(1);
87     }
88
89     if ($> != 0) {
90         die "This script should almost always be run as root.  Use the\n"
91             . "--requirements-met option to run as non-root.\n";
92     }
93 }
94
95 # Make sure the AFS client is not already running.
96 open(MOUNT, "mount |") or die "Failed to run mount: $!\n";
97 while(<MOUNT>) {
98     if (m:^AFS:) {
99         print "The AFS client is currently running on this workstation.\n";
100         print "Please restart this script after running"
101             . " /etc/init.d/openafs-client stop\n";
102         exit(1);
103     }
104 }
105 close MOUNT;
106
107 # Make sure there is a keyfile.
108 unless ( -f "/etc/openafs/server/KeyFile") {
109     print "You do not have an AFS keyfile.  Please create this using\n";
110     print "asetkey from openafs-krb5 or the bos addkey command\n";
111     exit(1);
112 }
113
114 # Stop the file server.
115 print "If the fileserver is not running, this may hang for 30 seconds.\n";
116 run("/etc/init.d/openafs-fileserver stop");
117
118 # Get the local hostname.  Use the fully-qualified hostname to be safer.
119 $server = `hostname -f`;
120 chomp $server;
121 my $ip = gethostbyname $server;
122 if (inet_ntoa($ip) eq '127.0.0.1') {
123     print "\n";
124     print "Your hostname $server resolves to 127.0.0.1, which AFS cannot\n";
125     print "cope with.  Make sure your hostname resolves to a non-loopback\n";
126     print "IP address.  (Check /etc/hosts and make sure that your hostname\n";
127     print "isn't listed on the 127.0.0.1 line.  If it is, removing it from\n";
128     print "that line will probably solve this problem.)\n";
129     exit(1);
130 }
131
132 # Determine the admin principal.
133 $admin = $rl->readline("What administrative principal should be used? ")
134     unless $admin;
135 print "\n";
136 die "Please specify an administrative user\n" unless $admin;
137 my $afs_admin = $admin;
138 $afs_admin =~ s:/:.:g;
139 if ($afs_admin =~ /@/) {
140     die "The administrative user must be in the same realm as the cell and\n"
141         . "no realm may be specified.\n";
142 }
143
144 # Determine the local cell.  This should be configured via debconf, from the
145 # openafs-client configuration, when openafs-fileserver is installed.
146 open(CELL, "/etc/openafs/server/ThisCell")
147     or die "Cannot open /etc/openafs/server/ThisCell: $!\n";
148 my $cell = <CELL>;
149 chomp $cell;
150
151 # Make sure the new cell is configured in the client CellServDB.
152 open(CELLSERVDB, "/etc/openafs/CellServDB")
153     or die "Cannot open /etc/openafs/CellServDB: $!\n";
154 my $found = 0;
155 while (<CELLSERVDB>) {
156     next unless /^>\Q$cell\E\s/;
157     while (<CELLSERVDB>) {
158         last if /^>/;
159         my ($dbserver) = split ' ';
160         if ($dbserver eq inet_ntoa($ip)) {
161             $found = 1;
162             last;
163         }
164     }
165     last;
166 }
167 unless ($found) {
168     print "\n";
169     print "The new cell $cell is not configured in /etc/openafs/CellServDB\n";
170     print "Add configuration like:\n\n";
171     print ">$cell\n";
172     print inet_ntoa($ip), "\n\n";
173     print "to that file before continuing.\n";
174     exit(1);
175 }
176
177 # Write out a new CellServDB for the local cell containing only this server.
178 if (-f "/etc/openafs/server/CellServDB") {
179     print "/etc/openafs/server/CellServDB already exists, renaming to .old\n";
180     rename("/etc/openafs/server/CellServDB",
181            "/etc/openafs/server/CellServDB.old")
182         or die "Cannot rename /etc/openafs/server/CellServDB: $!\n";
183 }
184 open(CELLSERVDB, "> /etc/openafs/server/CellServDB")
185     or die "Cannot create /etc/openafs/server/CellServDB: $!\n";
186 print CELLSERVDB ">$cell\n";
187 print CELLSERVDB inet_ntoa($ip), "\t\t\t#$server\n";
188 close CELLSERVDB or die "Cannot write to /etc/openafs/server/CellServDB: $!\n";
189
190 # Now, we should be able to start bos and add the admin user.
191 run("/etc/init.d/openafs-fileserver start");
192 $shutdown_needed = 1;
193 run("bos adduser $server $afs_admin -localauth");
194 unwind("bos removeuser $server $afs_admin -localauth");
195
196 # Create the initial protection database using pt_util.  This is safer than
197 # the standard mechanism of starting the cell in noauth mode until the first
198 # user has been created.
199 if (-f "/var/lib/openafs/db/prdb.DB0") {
200     warn "ERROR: Protection database already exists; cell already partially\n";
201     warn "ERROR: created.   If you do not want the current database, remove\n";
202     warn "ERROR: all files in /var/lib/openafs/db and then run this program\n";
203     warn "ERROR: again.\n";
204     exit(1);
205 }
206 print "\nCreating initial protection database.  This will print some errors\n";
207 print "about an id already existing and a bad ubik magic.  These errors can\n";
208 print "be safely ignored.\n\n";
209 open(PRDB, "| pt_util -p /var/lib/openafs/db/prdb.DB0 -w")
210     or die "Unable to start pt_util: $!\n";
211 print PRDB "$afs_admin 128/20 1 -204 -204\n";
212 print PRDB "system:administrators 130/20 -204 -204 -204\n";
213 print PRDB " $afs_admin 1\n";
214 close PRDB;
215 unwind("rm /var/lib/openafs/db/prdb*");
216 print "\n";
217
218 # We should now be able to start ptserver and vlserver.
219 run("bos create $server ptserver simple /usr/lib/openafs/ptserver -localauth");
220 unwind("bos delete $server ptserver -localauth");
221 run("bos create $server vlserver simple /usr/lib/openafs/vlserver -localauth");
222 unwind("bos delete $server vlserver -localauth");
223
224 # Create a file server as well.
225 run("bos create $server fs fs"
226     . " -cmd /usr/lib/openafs/fileserver"
227     . " -cmd /usr/lib/openafs/volserver"
228     . " -cmd /usr/lib/openafs/salvager -localauth");
229 unwind("bos delete $server fs -localauth");
230
231 # Pause for a while for ubik to catch up.
232 print "Waiting for database elections: ";
233 sleep(30);
234 print "done.\n";
235
236 # Past this point we want to control when bos shutdown happens.
237 $shutdown_needed = 0;
238 unwind("bos shutdown $server -localauth -wait");
239 run("vos create $server a root.afs -localauth");
240 unwind("vos remove $server a root.afs -localauth");
241
242 # We should now be able to bring up the client (it may need root.afs to exist
243 # if not using dynroot).  We override whatever default cell was configured for
244 # the client, just in case it was pointing to some other cell.
245 open(THIS, "> /etc/openafs/ThisCell")
246     or die "ERROR: Cannot create /etc/openafs/ThisCell: $!\n";
247 print THIS "$cell\n";
248 close THIS or die "ERROR: Cannot write to /etc/openafs/ThisCell: $!\n";
249 run("/etc/init.d/openafs-client force-start");
250
251 # Verify that AFS has managed to start.
252 my $afs_running = 0;
253 open(MOUNT, "mount |") or die "ERROR: Failed to run mount: $!\n";
254 while(<MOUNT>) {
255     if (m:^AFS:) {
256         $afs_running = 1;
257     }
258 }
259 unless ($afs_running) {
260     print "ERROR: The AFS client failed to start.\n";
261     print "ERROR: Please fix whatever problem kept it from running.\n";
262     exit(1);
263 }
264 print "\n";
265 print "Now, get tokens as $admin in the $cell cell.\n";
266 print "Then, run afs-rootvol.\n";
267
268 # Success, so clear the unwind commands.
269 @unwinds = ();
270
271 # If we fail before all the instances are created, we need to back out of
272 # everything we did as much as possible.
273 END {
274     if ($shutdown_needed || @unwinds) {
275         print "\nCell setup failed, ABORTING\n";
276     }
277     system("bos shutdown $server -localauth -wait") if $shutdown_needed;
278     run(pop @unwinds) while @unwinds;
279 }