lilalo
diff lm @ 1:ff93ad94d73b
LiLaLo -- Live Lab Log
(L3)
Система автоматического ведения журналов
и автоматизированного управления ходом
лабораторных работ.
(L3)
Система автоматического ведения журналов
и автоматизированного управления ходом
лабораторных работ.
author | devi |
---|---|
date | Sun May 22 16:29:55 2005 +0300 (2005-05-22) |
parents | |
children | 6c1d2b9f45e7 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/lm Sun May 22 16:29:55 2005 +0300 1.3 @@ -0,0 +1,494 @@ 1.4 +#!/usr/bin/perl 1.5 + 1.6 + 1.7 +use strict; 1.8 +use Inline::Files; 1.9 +use Data::Dumper; 1.10 +use Switch; 1.11 +use XML::Simple; 1.12 +use Getopt::Long; 1.13 + 1.14 +our $XMLClass; 1.15 +our $XMLCourse; 1.16 +our @Labs; 1.17 + 1.18 +our %Machines; # Machines list from class.xml 1.19 +our @SelectedMachines; # Machines list given as the command line argument 1.20 + 1.21 +our $Config_File = "labmaker.conf"; 1.22 +our %Config = ( 1.23 + "show_host" => "no", 1.24 + 1.25 + # Каталоги 1.26 + "path_labmaker" => "/var/labmaker/", 1.27 + "path_classes" => "/var/labmaker/classes/", 1.28 + "lablogs_path" => "/var/labmaker/lablogs/", 1.29 + "courses_path" => "/var/labmaker/courses/", 1.30 + "outpath" => "/var/labmaker/out/", 1.31 + 1.32 + # Файлы 1.33 + "runfile" => "lm.run", 1.34 + "logfile" => "lm.log", 1.35 + 1.36 + "class" => "class", # Имя файла класса 1.37 + "class_suffix" => ".xml", # Cуффикс файла класса 1.38 + 1.39 + "sshkey" => "$ENV{HOME}/.ssh/id_dsa.pub", 1.40 + "lmssh" => "./lm-ssh", 1.41 + "lminstall" => "./lm-install", 1.42 + "ssh_user" => "r", 1.43 +); 1.44 + 1.45 +our %Run = ( 1.46 + "lab" => "" 1.47 +); 1.48 + 1.49 +our %Scripts; 1.50 + 1.51 +sub load_class; 1.52 +sub load_config; 1.53 +sub load_course; 1.54 +sub load_scripts; 1.55 + 1.56 +sub lm_next; 1.57 +sub lm_prev; 1.58 +sub lm_start; 1.59 +sub lm_stop; 1.60 +sub lm_set; 1.61 +sub lm_do; 1.62 +sub lm_report; 1.63 +sub lm_show_hosts; 1.64 +sub lm_show_labs; 1.65 + 1.66 +sub load_run; 1.67 +sub save_run; 1.68 +sub print_log; 1.69 +sub print_usage_info; 1.70 +sub main(); 1.71 + 1.72 +main(); 1.73 + 1.74 +sub main() 1.75 +{ 1.76 + binmode STDOUT, ":utf8"; 1.77 + 1.78 + if (! @ARGV) { 1.79 + print_usage_info(); 1.80 + exit(0); 1.81 + } 1.82 + 1.83 + load_config; 1.84 + load_run; 1.85 + load_scripts; 1.86 + load_class; 1.87 + load_course; 1.88 + 1.89 + my $arg = join " ", @ARGV; 1.90 + 1.91 + # Getting @SelectedMachines if any 1.92 + if ($arg =~ s/@(.*?)\s//) { 1.93 + my $machines = $1; 1.94 + my @list = split /,/, $machines; 1.95 + for my $interval (@list) { 1.96 + my ($first, $last) = split /-/, $interval; 1.97 + 1.98 + push @SelectedMachines, $first; 1.99 + while ($first < $last) { 1.100 + push @SelectedMachines, ++$first; 1.101 + } 1.102 + } 1.103 + } 1.104 + 1.105 + # Choose command to do 1.106 + switch ($arg) { 1.107 + case "next" { lm_next } 1.108 + case "prev" { lm_prev } 1.109 + case /set / { $arg =~ /set (.*)/; lm_set $1 } 1.110 + case "report" { lm_report } 1.111 + case "start" { lm_start } 1.112 + case "stop" { lm_stop } 1.113 + case "show hosts" { lm_show_hosts } 1.114 + case "show labs" { lm_show_labs } 1.115 + case /do / { $arg =~ /do (.*)/; lm_do "$1" } 1.116 + else { print_usage_info() } 1.117 + } 1.118 + save_run; 1.119 + exit(0); 1.120 +} 1.121 + 1.122 +sub load_scripts 1.123 +{ 1.124 + local $/; 1.125 + $_=<SCRIPTS>; 1.126 + %Scripts = ("empty-element", split (/###(.*)\n/)); 1.127 + delete($Scripts{"empty-element"}); 1.128 +} 1.129 + 1.130 +sub load_config 1.131 +{ 1.132 + my %file_config; 1.133 + my %argv_config; 1.134 + #read_config_file(\%file_config, $Config_File); 1.135 + GetOptions(\%argv_config, map "$_=s", keys %Config); 1.136 + %Config = (%Config, %file_config, %argv_config); 1.137 +} 1.138 + 1.139 +sub load_course 1.140 +{ 1.141 + $XMLCourse = XMLin($Config{"courses_path"}.$XMLClass->{"course"}.".xml", ForceArray => 1 ) 1.142 + or die "Can't open file of the course ",$XMLClass->{"course"}," [with .xml extension]\n"; 1.143 +# print Dumper($XMLCourse); 1.144 + for my $lab (@{$XMLCourse->{"module"}}) { 1.145 + push @Labs, $lab->{"code"}; 1.146 + } 1.147 +} 1.148 + 1.149 +sub load_class 1.150 +{ 1.151 + my $classfile = 1.152 + $Config{"path_classes"}."/".$Config{"class"}.$Config{"class_suffix"}; 1.153 + $XMLClass = XMLin($classfile , ForceArray => [ 'student' ] ) 1.154 + or die "Can't open file of the class ",$classfile,"\n"; 1.155 + 1.156 + for my $student (@{$XMLClass->{"student"}}) { 1.157 + $Machines{$student->{"host"}} = { 1.158 + "name" => "$student->{firstname} $student->{surname}", 1.159 + "user" => "$student->{user}", 1.160 + "student" => $student, 1.161 + } 1.162 + } 1.163 +# print Dumper($XMLClass); 1.164 +# print Dumper(\%Machines); 1.165 +} 1.166 + 1.167 + 1.168 +sub lm_next 1.169 +{ 1.170 + for(my $i=0; $i<=$#Labs; $i++){ 1.171 + if ( $Labs[$i] eq $Run{"lab"} ) { 1.172 + if ($i < $#Labs) { 1.173 + lm_set($Labs[$i+1]); 1.174 + return ; 1.175 + } else { 1.176 + die "Lab ", $Run{"lab"}, " is the last. Switch to next lab is impossible" 1.177 + } 1.178 + } 1.179 + 1.180 + } 1.181 + die "Lab ", $Run{"lab"}, " not found. Don't know which is next" 1.182 +} 1.183 + 1.184 +sub lm_prev 1.185 +# Switch to previous lab 1.186 +{ 1.187 + for(my $i=0; $i<=$#Labs; $i++){ 1.188 + if ( $Labs[$i] eq $Run{"lab"} ) { 1.189 + if ($i > 0) { 1.190 + lm_set($Labs[$i-1]); 1.191 + return ; 1.192 + } else { 1.193 + die "Lab ", $Run{"lab"}, " is the first. Switch to previous lab is impossible" 1.194 + } 1.195 + } 1.196 + 1.197 + } 1.198 + die "Lab ", $Run{"lab"}, " not found. Don't know which is previous" 1.199 +} 1.200 + 1.201 +sub lm_set 1.202 +# Switch to $_[0] lab 1.203 +# FIXME 1.204 +{ 1.205 + my $lab = shift; 1.206 + print "Current lab is $lab\n"; 1.207 + $Run{"lab"} = "$lab"; 1.208 + lm_do "setlab", $lab; 1.209 +} 1.210 + 1.211 + 1.212 +sub lm_start 1.213 +# Start new training day 1.214 +{ 1.215 + print_log(`date`." STARTED\n"); 1.216 + if ($Run{"lab"}) { 1.217 + lm_next; 1.218 + } 1.219 + else 1.220 + { 1.221 + # First lab in the course 1.222 + lm_set($Labs[0]); 1.223 + } 1.224 +} 1.225 + 1.226 +sub lm_stop 1.227 +# Stop this training day 1.228 +{ 1.229 + print_log(`date`." STOPPED\n"); 1.230 +} 1.231 + 1.232 + 1.233 +sub lm_show_hosts 1.234 +# Show hosts used to run a commands 1.235 +{ 1.236 + my $i=1; 1.237 + for my $m (sort keys %Machines) { 1.238 + if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) { 1.239 + print "($i)","\t",$m,"\t",$Machines{$m}->{"name"},"\n"; 1.240 + } 1.241 + $i++; 1.242 + } 1.243 +} 1.244 + 1.245 +sub lm_show_labs 1.246 +# Show hosts used to run a commands 1.247 +{ 1.248 + my $i=1; 1.249 + for my $lab (@Labs) { 1.250 + print $lab; 1.251 + print "*" if $lab eq $Run{"lab"}; 1.252 + print "\n"; 1.253 + } 1.254 +} 1.255 + 1.256 +sub lm_do 1.257 +# Do the $_[0] command on all of the hosts 1.258 +{ 1.259 + my $command = shift; 1.260 + my $arg = join " ", @_; 1.261 + my $i=1; 1.262 + for my $m (sort keys %Machines) { 1.263 + if (!@SelectedMachines || grep $_ eq $i, @SelectedMachines) { 1.264 + print "$m:\n" if $Config{"show_host"} =~ /y/i; 1.265 + 1.266 + my %myenv = ( %Config, 1.267 + host => $m, 1.268 + dirs => "/root /home/".$Machines{$m}->{"user"}, 1.269 + lablogs => $Config{"lablogs_path"}."/". 1.270 + $XMLClass->{"course"}."/". 1.271 + $XMLClass->{"date"}."/". 1.272 + "$m", 1.273 + lab => $arg, 1.274 + 1.275 + email => $Machines{$m}->{"student"}->{"email"}, 1.276 + company => $Machines{$m}->{"student"}->{"company"}, 1.277 + center => $XMLClass->{"center"}, 1.278 + course => $XMLClass->{"course"}, 1.279 + date => $XMLClass->{"date"}, 1.280 + name => $Machines{$m}->{"name"}, 1.281 + coursepath => $XMLCourse->{"path"}, 1.282 + 1.283 + ); 1.284 + if (grep { $_ eq $command} keys %Scripts) { 1.285 + $_=$Scripts{"$command"}; 1.286 + s/\$(\w+)/$myenv{$1}/ge; 1.287 + open(SHELL, "|/bin/sh -s"); 1.288 + binmode SHELL, ":utf8"; 1.289 + print SHELL $_; 1.290 + close (SHELL); 1.291 + } 1.292 + else { 1.293 + my $res = `ssh $Config{"ssh_user"}\@$m $command`; 1.294 + if ($res) { 1.295 + my $count = ($res =~ s/(^)/$m: /mg); 1.296 + print $res; 1.297 + print "\n" if ($count > 1); 1.298 + } 1.299 + } 1.300 + } 1.301 + $i++; 1.302 + } 1.303 +} 1.304 + 1.305 + 1.306 +sub lm_report 1.307 +{ 1.308 + 1.309 + print "Not implemented yet\n"; 1.310 + exit(1); 1.311 + 1.312 +=cut comment 1.313 + 1.314 +Дальше идут скрипты, код которых нужно реализовать здесь. 1.315 +Как минимум. 1.316 + 1.317 +=cut 1.318 + 1.319 + my $lm_script_make_report_web = <<'SCRIPT'; 1.320 + 1.321 +#!/bin/sh 1.322 + 1.323 +####cd /home/devi/lm 1.324 +./lm do copy-lablogs 1.325 +##./lm-report --input /home/murk/.labmaker --output /var/www/lm/murk.html 1.326 +##exit 1.327 + 1.328 +COURSE=ug-h 1.329 +DATE=2005-04-25 1.330 +SUFF=".linux.nt" 1.331 +#MACHINES="m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15" 1.332 +#MACHINES="m1 m2 m3 m4 m5 m6 m7 f1 f2 f3 f4 f5" 1.333 +MACHINES="m01 m02 m03 m04 m05 m06 m07 m08" 1.334 +#MACHINES="m1" 1.335 +USERS="user root" 1.336 +WEBDIR=/var/www/lm 1.337 + 1.338 +for u in $USERS 1.339 + do 1.340 + for m in $MACHINES 1.341 + do 1.342 + e=utf-8 1.343 + [ "${m##f}" = "$m" ] || e=koi8-r 1.344 + #e=koi8-r 1.345 + mkdir -p $WEBDIR/$DATE/$m 1.346 + cp share/*.ico share/*.css $WEBDIR/$m 1.347 + #echo Processing Lablogs/$COURSE/$DATE/$m$SUFF/$u/ 1.348 + ./lm-report\ 1.349 + --input Lablogs/$COURSE/$DATE/$m$SUFF/$u/ \ 1.350 + --diffs "Lablogs/$COURSE/$DATE/$m$SUFF/$u/ Lablogs/$COURSE/$DATE/$m$SUFF/root/"\ 1.351 + --output /var/www/lm/$DATE/$m/$u.html \ 1.352 + --encoding $e 1.353 + done 1.354 + done 1.355 + 1.356 + 1.357 +SCRIPT 1.358 + 1.359 + my $lm_script_make_report_all = <<'SCRIPT'; 1.360 + 1.361 +#!/bin/sh 1.362 +WEBDIR=/var/www/lm 1.363 + 1.364 +find . -type d -maxdepth 5 -mindepth 5 |\ 1.365 + while read dir 1.366 + do 1.367 + subdir=${dir##Lablogs/} 1.368 + e=utf-8 1.369 + echo $dir | grep -qi bsd && e=koi8-r 1.370 + echo $dir | grep -qi /f && e=koi8-r 1.371 + 1.372 + mkdir -p $WEBDIR/${subdir%/*} 1.373 + cp share/*.ico share/*.css $WEBDIR/${subdir%/*} 1.374 + #echo Processing Lablogs/$COURSE/$DATE/$m$SUFF/$u/ 1.375 + ./lm-report\ 1.376 + --input $dir \ 1.377 + --diffs "${dir%/user}/root $dir"\ 1.378 + --output $WEBDIR/$subdir.html \ 1.379 + --encoding $e 1.380 + done 1.381 + 1.382 +SCRIPT 1.383 +} 1.384 + 1.385 +sub load_run 1.386 +{ 1.387 + my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"}; 1.388 + open (RUN, $runfile) 1.389 + or return; 1.390 + while (<RUN>) { 1.391 + chomp; 1.392 + my ($var, $val) = split /\s+/,$_,2; 1.393 + $Run{$var}=$val; 1.394 + } 1.395 + close (RUN); 1.396 +} 1.397 + 1.398 +sub save_run 1.399 +{ 1.400 + my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"}; 1.401 + open (RN, "$runfile") 1.402 + or die "Can't save running state to $runfile"; 1.403 + for my $var (keys %Run) { 1.404 + print RN $var,"\t",$Run{$var},"\n"; 1.405 + } 1.406 + close (RN); 1.407 +} 1.408 + 1.409 +sub print_log 1.410 +{ 1.411 + my $logfile = $Config{"path_labmaker"}."/".$Config{"path_logfile"}; 1.412 + open (LOG, ">>$logfile") 1.413 + or die "Can't open logfile $logfile for writing"; 1.414 + print LOG @_; 1.415 + close (LOG); 1.416 +} 1.417 + 1.418 + 1.419 +sub print_usage_info 1.420 +{ 1.421 + print "Usage:\n\n\t$0 [host-list] command\n"; 1.422 + while (<USAGE>) { 1.423 + print $_; 1.424 + } 1.425 +} 1.426 + 1.427 +__USAGE__ 1.428 + 1.429 +Commands: 1.430 + 1.431 + next -- next lab 1.432 + prev -- prev lab 1.433 + set LAB -- set current lab to LAB 1.434 + start -- start this day training 1.435 + stop -- stop this day training 1.436 + show hosts -- show available hosts in the class 1.437 + show labs -- show available labs in the course 1.438 + do COMMAND -- do specified command on the hosts of hostlist 1.439 + report -- generate XML/HTML reports 1.440 + 1.441 + 1.442 +do commands: 1.443 + 1.444 + install [PROFILE] -- install profile 1.445 + 1.446 +Host list: 1.447 + 1.448 + @N -- machine N 1.449 + @N1-N2 -- all of the machines from N1 to N2 1.450 + @N1,N2,N3 -- machine N1, N2 and N3 1.451 + 1.452 + N* is numbers or domain names of the machines. 1.453 + 1.454 + If host list is not specified, 1.455 + command is executed on all of the machines 1.456 + 1.457 + 1.458 + 1.459 +__SCRIPTS__ 1.460 +###install 1.461 +cat $sshkey | $lmssh $ssh_user@$host /bin/sh -c '"mkdir -p ~/.ssh; cat >>~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys"' 1.462 + 1.463 +###install-lm 1.464 +cat $lminstall | ssh $ssh_user@$host /bin/sh -s $dirs 1.465 + 1.466 +###copy-lablogs 1.467 +for i in $dirs 1.468 +do 1.469 + mkdir -p $lablogs/${i##*/} 1.470 + scp -q $ssh_user@$host:${i}/.labmaker/* $lablogs/${i##*/} 1.471 +done 1.472 + 1.473 +###setlab 1.474 +for i in $dirs 1.475 +do 1.476 + echo $lab | ssh $ssh_user@$host "cat > "${i}"/.labmaker/lab" 1.477 +done 1.478 + 1.479 +###makeout 1.480 +common=$course-$date 1.481 +personal=$course-$date-$email 1.482 +mkdir -p $outpath/${common}/{Lablogs,Docs} 1.483 +mkdir -p $outpath/${personal}/{Course,Files} 1.484 +cd $outpath/${personal} 1.485 +ln -s ../${common}/Lablogs . 1.486 +ln -s ../${common}/Docs . 1.487 +cd ~- 1.488 +export UG_PERSONAL=${PWD}/$outpath/${personal}/Course 1.489 +export UG_CENTER="$center" 1.490 +export UG_COURSE="$course" 1.491 +export UG_DATE="$date" 1.492 +export UG_STUDENT="$name" 1.493 +export UG_COMPANY="$company" 1.494 +cd $coursepath; make personal; cd ~- 1.495 + 1.496 +###watch 1.497 +cat taillast.pl | ssh $ssh_user@$host perl - /root/.labmaker