Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tests / OpenAFS / OS.pm
1 # This is -*- perl -*-
2
3 package OpenAFS::OS;
4 use warnings;
5 use strict;
6 use OpenAFS::Dirpath;
7 use OpenAFS::ConfigUtils;
8
9 my $path = $OpenAFS::Dirpath::openafsdirpath;
10
11 #
12 # Create the named system object for OS specific init scripts
13 # and commands.
14 #
15 sub create {
16 my $class = _get_class($path->{'ostype'});
17 $class->new(@_);
18 }
19
20 #
21 # Create the OS object.
22 #
23 sub new {
24 my $class = shift;
25 my $self = {
26 'debug'=>0,
27 'ostype'=>$path->{'ostype'},
28 @_,
29 };
30
31 $self = bless($self, $class);
32 $self->{'syscnf'} = "$path->{'initdir'}/test-afs-rc.conf";
33 $self->{'commands'} = $self->get_commands();
34 return $self;
35 }
36
37 #
38 # _get_class(name) - Return the package name for the ostype
39 #
40 sub _get_class {
41 my $type = shift;
42 if ($type=~/linux/i) {
43 return "OpenAFS::OS::Linux";
44 }
45 die "error: Unknow system type. Valid types are: linux\n";
46 }
47
48 #
49 # command(name [,params...]) - Return the command string or code reference.
50 #
51 sub command {
52 my $self = shift;
53 my $name = shift;
54 my $cmd = $self->{'commands'}->{$name};
55 unless (defined $cmd) {
56 die "error: Unsupported command name $name for OS type $self->{'ostype'}\n";
57 }
58 # add parameters if present.
59 if (scalar @_) {
60 if (ref($cmd) eq 'CODE') {
61 $cmd = sub { &$cmd(@_) };
62 }
63 else {
64 $cmd = join(' ', ($cmd, @_));
65 }
66 }
67 return $cmd;
68 }
69
70 #--------------------------------------------------------------
71 # Common unix style os commands.
72 package OpenAFS::OS::Unix;
73 use warnings;
74 use strict;
75 use OpenAFS::ConfigUtils;
76 use OpenAFS::Dirpath;
77 our @ISA = qw(OpenAFS::OS);
78
79 #
80 # remove(target) - recursive remove
81 #
82 sub remove {
83 my $self = shift;
84 my $target = shift;
85 run("rm -rf $target");
86 }
87
88 #
89 # Start the server.
90 #
91 sub fileserver_start {
92 my $self = shift;
93 run("$path->{'afssrvsbindir'}/bosserver");
94 }
95
96 #
97 # Stop the server.
98 #
99 sub fileserver_stop {
100 my $self = shift;
101 my @bosserver_pids = $self->find_pids("bosserver");
102 if (scalar @bosserver_pids) {
103 # bosserver is running, try to shutdown with bos.
104 eval {
105 run("$path->{'afssrvbindir'}/bos shutdown localhost -localauth");
106 };
107 if ($@) {
108 warn "WARNING: Shutdown command failed.\n";
109 }
110 # Now shutdown bosserver process itself. Kill all of them
111 # in case there are remants.
112 foreach my $pid (@bosserver_pids) {
113 eval { run("kill $pid") };
114 }
115 }
116 }
117
118 #
119 # Restart the server.
120 #
121 sub fileserver_restart {
122 my $self = shift;
123 fileserver_stop();
124 fileserver_start();
125 }
126
127 #
128 # Return a list of pids.
129 #
130 sub find_pids {
131 my $self = shift;
132 my $process = shift;
133 my @pids = ();
134 my $ps = "ps -e -o pid,cmd";
135 if ($self->{'debug'}) {
136 print("debug: searching for process $process\n");
137 }
138 open(PS, "$ps |") or die "Cannot run command: $ps: $!";
139 while (<PS>) {
140 chomp;
141 my ($pid,$cmd) = split;
142 if ($cmd=~/$process/) {
143 if ($self->{'debug'}) {
144 print("debug: found $pid $cmd\n");
145 }
146 push(@pids, $pid);
147 }
148 }
149 close PS;
150 return @pids;
151 }
152
153 #
154 # Returns the number of pids found for a program name.
155 #
156 sub number_running {
157 my $self = shift;
158 my $program = shift;
159 my @pids = $self->find_pids($program);
160 return scalar @pids;
161 }
162
163 #--------------------------------------------------------------
164 package OpenAFS::OS::Linux;
165 use warnings;
166 use strict;
167 use OpenAFS::ConfigUtils;
168 use OpenAFS::Dirpath;
169 our @ISA = qw(OpenAFS::OS::Unix);
170
171 #
172 # OS-specific commands. Defer to init scripts where possible.
173 #
174 sub get_commands {
175 my $self = shift;
176
177 my $commands = {
178 'client-start' => "SYSCNF=$self->{'syscnf'} $path->{'initdir'}/afs.rc start",
179 'client-stop' => "SYSCNF=$self->{'syscnf'} $path->{'initdir'}/afs.rc stop",
180 'client-restart' => "SYSCNF=$self->{'syscnf'} $path->{'initdir'}/afs.rc restart",
181 'client-forcestop' => sub { $self->client_forcestop() },
182 'fileserver-start' => sub { $self->fileserver_start() },
183 'fileserver-stop' => sub { $self->fileserver_stop() },
184 'fileserver-restart' => sub { $self->fileserver_restart() },
185 'remove' => 'rm -rf',
186 };
187 return $commands;
188 }
189
190 #
191 # Setup the init script configuration, including the install paths.
192 # Create the required directories for the client, /afs and the
193 # cache directory.
194 #
195 # N.B.The cacheinfo file is created by the init script.
196 #
197 sub configure_client {
198 my $self = shift;
199 my $config = {
200 # defaults
201 'cachesize' => '50000',
202 # custom
203 @_,
204 };
205
206 my $debug = $self->{'debug'};
207
208 open (SYSCNF, "> $self->{'syscnf'}") or
209 die "error: Cannot open afs.rc configuration file $self->{'syscnf'}, $!\n";
210
211 print "debug: creating afs.rc configuration file $self->{'syscnf'}\n" if $debug;
212 print SYSCNF <<"_SYSCNF_";
213 AFS_CLIENT=on
214 AFS_SERVER=off
215 ENABLE_AFSDB=off
216 ENABLE_DYNROOT=off
217 CACHESIZE=$config->{'cachesize'}
218 OPTIONS="-confdir $path->{'viceetcdir'}"
219 WAIT_FOR_SALVAGE=no
220 AFSDIR=/afs
221 CACHEDIR=$path->{'cachedir'}
222 CACHEINFO=$path->{'viceetcdir'}/cacheinfo
223 VERBOSE=
224 AFS_POST_INIT=
225 AFSD=$path->{'afsddir'}/afsd
226 BOSSERVER=$path->{'afssrvsbindir'}/bosserver
227 BOS=$path->{'afssrvbindir'}/bos
228 KILLAFS=$path->{'viceetcdir'}/killafs
229 MODLOADDIR=$path->{'afskerneldir'}
230 _SYSCNF_
231 close SYSCNF;
232 if ($debug) {
233 if (open(SYSCNF, "< $self->{'syscnf'}")) {
234 while (<SYSCNF>) {
235 chomp; print "debug: $_\n";
236 }
237 close SYSCNF;
238 }
239 }
240
241 # Create a cache directory if none.
242 unless ( -d "$path->{'cachedir'}" ) {
243 print "debug: making cache directory: $path->{'cachedir'}\n" if $debug;
244 system("mkdir -p $path->{'cachedir'}");
245 system("chmod 0700 $path->{'cachedir'}");
246 }
247
248 # Create the local /afs directory on which the afs filespace will be mounted.
249 if ( ! -d "/afs" ) {
250 print "debug: making the local /afs directory.\n" if $debug;
251 system("mkdir /afs");
252 system("chmod 0777 /afs");
253 }
254 }
255
256 #
257 # Force the client to stop. The sequence is:
258 # umount /afs
259 # /usr/vice/etc/afsd -shutdown
260 # rmmod openafs (or rmmod libafs)
261 #
262 sub client_forcestop {
263 my $self = shift;
264 print "debug: client forcestop\n" if $self->{'debug'};
265
266 eval {
267 run("umount /afs");
268 sleep 1;
269 };
270 eval {
271 run("$path->{'afsddir'}/afsd -shutdown");
272 sleep 1;
273 };
274
275 # Remove openafs modules still loaded.
276 my $mods = $self->list_modules();
277 if ($mods->{'openafs'}) {
278 eval { run("/sbin/rmmod openafs") };
279 }
280 if ($mods->{'libafs'}) {
281 eval { run("/sbin/rmmod libafs") };
282 }
283
284 # Check.
285 $mods = $self->list_modules();
286 if ($mods->{'openafs'}) {
287 print "warning: kernel module still loaded: openafs\n";
288 }
289 if ($mods->{'libafs'}) {
290 print "warning: kernel module still loaded: libafs\n";
291 }
292
293 # remove stale lock set by init script.
294 run("rm -f /var/lock/subsys/afs");
295 }
296
297 #
298 # list_modules() - Returns a table of loaded module names.
299 #
300 sub list_modules {
301 my $self = shift;
302 my $mods = {};
303 if (open(LSMOD, "/sbin/lsmod |")) {
304 while(<LSMOD>) {
305 chomp;
306 my ($mod) = split;
307 $mods->{$mod} = 1;
308 }
309 close LSMOD;
310 }
311 return $mods;
312 }
313
314 1;