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