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