Commit | Line | Data |
---|---|---|
b7cfede0 BK |
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 strict; | |
8 | use Debian::OpenAFS::ConfigUtils; | |
9 | use Term::ReadLine; | |
10 | use Getopt::Long; | |
11 | use vars qw($rl $server $part $requirements_met); | |
12 | ||
13 | =head1 NAME | |
14 | ||
15 | afs-rootvol - Generate and populate root volumes for new AFS cells. | |
16 | ||
17 | =head1 SYNOPSIS | |
18 | ||
19 | B<afs-rootvol> [B<--requirements-met>] [B<--server> I<server-name>] | |
20 | [B<--partition> I<partition-letter>] | |
21 | ||
22 | =head1 DESCRIPTION | |
23 | ||
24 | This script sets up an AFS cell's root volumes. It assumes that you already | |
25 | have a fileserver and database servers. The fileserver should have an empty | |
26 | root.afs. This script creates root.cell, user, and service and populates | |
27 | root.afs. | |
28 | ||
29 | =head1 AUTHOR | |
30 | ||
31 | Sam Hartman <hartmans@debian.org> | |
32 | ||
33 | =cut | |
34 | #'# cperl-mode | |
35 | ||
36 | # This subroutine creates a volume, mounts it and then sets the access | |
37 | # to allow read by anyuser. The volume is scheduled for deletion in | |
38 | # case of error. | |
39 | sub mkvol($$) { | |
40 | my ($vol, $mnt) = @_; | |
41 | run("vos create $server $part $vol -localauth"); | |
42 | unwind("vos remove $server $part $vol -localauth"); | |
43 | run("fs mkm $mnt $vol "); | |
44 | run("fs sa $mnt system:anyuser rl"); | |
45 | } | |
46 | ||
47 | # Main script. Flush all output immediately. | |
48 | $| = 1; | |
49 | $rl = new Term::ReadLine('AFS'); | |
50 | GetOptions ("requirements-met" => \$requirements_met, | |
51 | "server=s" => \$server, | |
52 | "partition=s" => \$part); | |
53 | unless ($requirements_met) { | |
54 | print <<eotext; | |
55 | Prerequisites | |
56 | ||
57 | In order to set up the root.afs volume, you must meet the following | |
58 | pre-conditions: | |
59 | ||
60 | 1) The cell must be configured, running a database server with a | |
61 | volume location and protection server. The afs-newcell script will | |
62 | set up these services. | |
63 | ||
64 | 2) You must be logged into the cell with tokens in for a user in | |
65 | system:administrators and with a principal that is in the UserList | |
66 | file of the servers in the cell. | |
67 | ||
68 | 3) You need a fileserver in the cell with partitions mounted and a | |
69 | root.afs volume created. Presumably, it has no volumes on it, | |
70 | although the script will work so long as nothing besides root.afs | |
71 | exists. The afs-newcell script will set up the file server. | |
72 | ||
73 | 4) The AFS client must be running pointed at the new cell. | |
74 | eotext | |
75 | ||
76 | $_ = $rl->readline("Do you meet these conditions? (y/n) "); | |
77 | unless (/^y/i ) { | |
78 | print "Please restart the script when you meet these conditions.\n"; | |
79 | exit(1); | |
80 | } | |
81 | if ($> != 0) { | |
82 | die "This script should almost always be run as root. Use the\n" | |
83 | . "--requirements-met option to run as non-root.\n"; | |
84 | } | |
85 | } | |
86 | ||
87 | # Get configuration information we need. | |
88 | open(CELL, "/etc/openafs/server/ThisCell") | |
89 | or die "Unable to find out what cell this machine serves: $!\n"; | |
90 | my $cell = <CELL>; | |
91 | close CELL; | |
92 | chomp $cell; | |
93 | ||
94 | unless ($server) { | |
95 | print <<eotext; | |
96 | ||
97 | You will need to select a server (hostname) and AFS partition on which to | |
98 | create the root volumes. | |
99 | ||
100 | eotext | |
101 | ||
102 | $server = $rl->readline("What AFS Server should volumes be placed on? "); | |
103 | die "Please select a server.\n" unless $server; | |
104 | } | |
105 | unless ($part) { | |
106 | $part = $rl->readline("What partition? [a] "); | |
107 | $part = "a" unless $part; | |
108 | } | |
109 | print "\n"; | |
110 | ||
111 | # Make sure the user has tokens. Forgetting to do this is a common error. | |
112 | my $status = system("tokens | grep Expires > /dev/null"); | |
113 | if ($status != 0) { | |
114 | die "You appear to not have AFS tokens. Obtain tokens (with aklog,\n" | |
115 | . "for example) and then run this script again.\n"; | |
116 | } | |
117 | ||
118 | # Figure out where root.afs is. There are two possibilities: either we aren't | |
119 | # running with dynroot, and root.afs is therefore accessible as /afs, or we | |
120 | # are running with dynroot, in which case we have to create root.cell first | |
121 | # and then mount root.afs under it. | |
122 | # | |
123 | # Always create root.cell first; we may need it if running with dynroot, and | |
124 | # it doesn't hurt to do it now regardless. | |
125 | my $rootmnt = "/afs"; | |
126 | run("vos create $server $part root.cell -localauth"); | |
127 | unwind("vos remove $server $part root.cell -localauth"); | |
128 | my $dynroot = (-d "$rootmnt/$cell/."); | |
129 | if ($dynroot) { | |
130 | run("fs mkm /afs/$cell/.root.afs root.afs -rw"); | |
131 | unwind("fs rmm /afs/$cell/.root.afs"); | |
132 | $rootmnt = "/afs/$cell/.root.afs"; | |
133 | } | |
134 | run("fs sa $rootmnt system:anyuser rl"); | |
135 | ||
136 | # Scan CellServDB and create the cell mount points for every cell found there. | |
137 | # Force these commands to succeed, since it's possible to end up with | |
138 | # duplicate entries in CellServDB (and the second fs mkm will fail). | |
139 | open(CELLSERVDB, "/etc/openafs/CellServDB") | |
140 | or die "Unable to open /etc/openafs/CellServDB: $!\n"; | |
141 | while (<CELLSERVDB>) { | |
142 | chomp; | |
143 | if (/^>\s*([a-z0-9_\-.]+)/) { | |
144 | run("fs mkm $rootmnt/$1 root.cell -cell $1 -fast || true"); | |
145 | unwind("fs rmm $rootmnt/$1 || true"); | |
146 | } | |
147 | } | |
148 | ||
149 | # Now, create the read/write mount points for root.cell and root.afs and set | |
150 | # root.cell system:anyuser read. | |
151 | run("fs sa /afs/$cell system:anyuser rl"); | |
152 | run("fs mkm $rootmnt/.$cell root.cell -cell $cell -rw"); | |
153 | unwind("fs rmm $rootmnt/.$cell"); | |
154 | run("fs mkm $rootmnt/.root.afs root.afs -rw"); | |
155 | unwind("fs rmm $rootmnt/.root.afs"); | |
156 | ||
157 | # Create the user and service mount point volumes to fit the semi-standard AFS | |
158 | # cell layout. | |
159 | mkvol("user", "/afs/$cell/user"); | |
160 | mkvol("service", "/afs/$cell/service"); | |
161 | ||
162 | # Strip the domain off of the cell name and create the short symlinks. | |
163 | $cell =~ /^([^.]+)/; | |
164 | my $cellpart = $1; | |
165 | if ($cellpart && $cellpart ne $cell) { | |
166 | run("ln -s $cell $rootmnt/$cellpart"); | |
167 | unwind("rm $rootmnt/$cellpart"); | |
168 | run("ln -s .$cell $rootmnt/.$cellpart"); | |
169 | unwind("rm $rootmnt/.$cellpart"); | |
170 | } | |
171 | if ($dynroot) { | |
172 | run("fs rmm /afs/$cell/.root.afs"); | |
173 | unwind("fs mkm /afs/$cell/.root.afs root.afs -rw"); | |
174 | } | |
175 | ||
176 | # Now, replicate the infrastructure volumes. | |
177 | run("vos addsite $server $part root.afs -localauth"); | |
178 | run("vos addsite $server $part root.cell -localauth"); | |
179 | run("vos release root.afs -localauth"); | |
180 | run("vos release root.cell -localauth"); | |
181 | unwind("vos remove $server $part root.cell.readonly -localauth"); | |
182 | unwind("vos remove $server $part root.afs.readonly -localauth"); | |
183 | ||
184 | # Success, so clear the unwind commands. | |
185 | @unwinds = (); | |
186 | ||
187 | # If we fail before all the instances are created, we need to back out of | |
188 | # everything we did as much as possible. | |
189 | END { | |
190 | if (@unwinds) { | |
191 | print "\nRoot volume setup failed, ABORTING\n"; | |
192 | } | |
193 | run(pop @unwinds) while @unwinds; | |
194 | } |