backport to buster
[hcoop/debian/openafs.git] / 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 . " service 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("service 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("service 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 -localauth");
236 unwind("bos delete $server dafs -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("service 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 }