#!/usr/bin/perl -w # Copyright (C) 2000 by Sam Hartman # This file may be copied either under the terms of the GNU GPL or the IBM # Public License either version 2 or later of the GPL or version 1.0 or later # of the IPL. use strict; use Debian::OpenAFS::ConfigUtils; use Term::ReadLine; use Getopt::Long; use vars qw($rl $server $part $requirements_met); =head1 NAME afs-rootvol - Generate and populate root volumes for new AFS cells. =head1 SYNOPSIS B [B<--requirements-met>] [B<--server> I] [B<--partition> I] =head1 DESCRIPTION This script sets up an AFS cell's root volumes. It assumes that you already have a fileserver and database servers. The fileserver should have an empty root.afs. This script creates root.cell, user, and service and populates root.afs. =head1 AUTHOR Sam Hartman =cut #'# cperl-mode # This subroutine creates a volume, mounts it and then sets the access # to allow read by anyuser. The volume is scheduled for deletion in # case of error. sub mkvol($$) { my ($vol, $mnt) = @_; run("vos create $server $part $vol -localauth"); unwind("vos remove $server $part $vol -localauth"); run("fs mkm $mnt $vol "); run("fs sa $mnt system:anyuser rl"); } # Main script. Flush all output immediately. $| = 1; $rl = new Term::ReadLine('AFS'); GetOptions ("requirements-met" => \$requirements_met, "server=s" => \$server, "partition=s" => \$part); unless ($requirements_met) { print <readline("Do you meet these conditions? (y/n) "); unless (/^y/i ) { print "Please restart the script when you meet these conditions.\n"; exit(1); } if ($> != 0) { die "This script should almost always be run as root. Use the\n" . "--requirements-met option to run as non-root.\n"; } } # Get configuration information we need. open(CELL, "/etc/openafs/server/ThisCell") or die "Unable to find out what cell this machine serves: $!\n"; my $cell = ; close CELL; chomp $cell; unless ($server) { print <readline("What AFS Server should volumes be placed on? "); die "Please select a server.\n" unless $server; } unless ($part) { $part = $rl->readline("What partition? [a] "); $part = "a" unless $part; } print "\n"; # Make sure the user has tokens. Forgetting to do this is a common error. my $status = system("tokens | grep Expires > /dev/null"); if ($status != 0) { die "You appear to not have AFS tokens. Obtain tokens (with aklog,\n" . "for example) and then run this script again.\n"; } # Figure out where root.afs is. There are two possibilities: either we aren't # running with dynroot, and root.afs is therefore accessible as /afs, or we # are running with dynroot, in which case we have to create root.cell first # and then mount root.afs under it. # # Always create root.cell first; we may need it if running with dynroot, and # it doesn't hurt to do it now regardless. my $rootmnt = "/afs"; run("vos create $server $part root.cell -localauth"); unwind("vos remove $server $part root.cell -localauth"); my $dynroot = (-d "$rootmnt/$cell/."); if ($dynroot) { run("fs mkm /afs/$cell/.root.afs root.afs -rw"); unwind("fs rmm /afs/$cell/.root.afs"); $rootmnt = "/afs/$cell/.root.afs"; } run("fs sa $rootmnt system:anyuser rl"); # Scan CellServDB and create the cell mount points for every cell found there. # Force these commands to succeed, since it's possible to end up with # duplicate entries in CellServDB (and the second fs mkm will fail). open(CELLSERVDB, "/etc/openafs/CellServDB") or die "Unable to open /etc/openafs/CellServDB: $!\n"; while () { chomp; if (/^>\s*([a-z0-9_\-.]+)/) { run("fs mkm $rootmnt/$1 root.cell -cell $1 -fast || true"); unwind("fs rmm $rootmnt/$1 || true"); } } # Now, create the read/write mount points for root.cell and root.afs and set # root.cell system:anyuser read. run("fs sa /afs/$cell system:anyuser rl"); run("fs mkm $rootmnt/.$cell root.cell -cell $cell -rw"); unwind("fs rmm $rootmnt/.$cell"); run("fs mkm $rootmnt/.root.afs root.afs -rw"); unwind("fs rmm $rootmnt/.root.afs"); # Create the user and service mount point volumes to fit the semi-standard AFS # cell layout. mkvol("user", "/afs/$cell/user"); mkvol("service", "/afs/$cell/service"); # Strip the domain off of the cell name and create the short symlinks. $cell =~ /^([^.]+)/; my $cellpart = $1; if ($cellpart && $cellpart ne $cell) { run("ln -s $cell $rootmnt/$cellpart"); unwind("rm $rootmnt/$cellpart"); run("ln -s .$cell $rootmnt/.$cellpart"); unwind("rm $rootmnt/.$cellpart"); } if ($dynroot) { run("fs rmm /afs/$cell/.root.afs"); unwind("fs mkm /afs/$cell/.root.afs root.afs -rw"); } # Now, replicate the infrastructure volumes. run("vos addsite $server $part root.afs -localauth"); run("vos addsite $server $part root.cell -localauth"); run("vos release root.afs -localauth"); run("vos release root.cell -localauth"); unwind("vos remove $server $part root.cell.readonly -localauth"); unwind("vos remove $server $part root.afs.readonly -localauth"); # Success, so clear the unwind commands. @unwinds = (); # If we fail before all the instances are created, we need to back out of # everything we did as much as possible. END { if (@unwinds) { print "\nRoot volume setup failed, ABORTING\n"; } run(pop @unwinds) while @unwinds; }