lilalo

annotate lm @ 1:ff93ad94d73b

LiLaLo -- Live Lab Log
(L3)

Система автоматического ведения журналов
и автоматизированного управления ходом
лабораторных работ.
author devi
date Sun May 22 16:29:55 2005 +0300 (2005-05-22)
parents
children 6c1d2b9f45e7
rev   line source
devi@0 1 #!/usr/bin/perl
devi@0 2
devi@0 3
devi@0 4 use strict;
devi@0 5 use Inline::Files;
devi@0 6 use Data::Dumper;
devi@0 7 use Switch;
devi@0 8 use XML::Simple;
devi@0 9 use Getopt::Long;
devi@0 10
devi@0 11 our $XMLClass;
devi@0 12 our $XMLCourse;
devi@0 13 our @Labs;
devi@0 14
devi@0 15 our %Machines; # Machines list from class.xml
devi@0 16 our @SelectedMachines; # Machines list given as the command line argument
devi@0 17
devi@0 18 our $Config_File = "labmaker.conf";
devi@0 19 our %Config = (
devi@0 20 "show_host" => "no",
devi@0 21
devi@0 22 # Каталоги
devi@0 23 "path_labmaker" => "/var/labmaker/",
devi@0 24 "path_classes" => "/var/labmaker/classes/",
devi@0 25 "lablogs_path" => "/var/labmaker/lablogs/",
devi@0 26 "courses_path" => "/var/labmaker/courses/",
devi@0 27 "outpath" => "/var/labmaker/out/",
devi@0 28
devi@0 29 # Файлы
devi@0 30 "runfile" => "lm.run",
devi@0 31 "logfile" => "lm.log",
devi@0 32
devi@0 33 "class" => "class", # Имя файла класса
devi@0 34 "class_suffix" => ".xml", # Cуффикс файла класса
devi@0 35
devi@0 36 "sshkey" => "$ENV{HOME}/.ssh/id_dsa.pub",
devi@0 37 "lmssh" => "./lm-ssh",
devi@0 38 "lminstall" => "./lm-install",
devi@0 39 "ssh_user" => "r",
devi@0 40 );
devi@0 41
devi@0 42 our %Run = (
devi@0 43 "lab" => ""
devi@0 44 );
devi@0 45
devi@0 46 our %Scripts;
devi@0 47
devi@0 48 sub load_class;
devi@0 49 sub load_config;
devi@0 50 sub load_course;
devi@0 51 sub load_scripts;
devi@0 52
devi@0 53 sub lm_next;
devi@0 54 sub lm_prev;
devi@0 55 sub lm_start;
devi@0 56 sub lm_stop;
devi@0 57 sub lm_set;
devi@0 58 sub lm_do;
devi@0 59 sub lm_report;
devi@0 60 sub lm_show_hosts;
devi@0 61 sub lm_show_labs;
devi@0 62
devi@0 63 sub load_run;
devi@0 64 sub save_run;
devi@0 65 sub print_log;
devi@0 66 sub print_usage_info;
devi@0 67 sub main();
devi@0 68
devi@0 69 main();
devi@0 70
devi@0 71 sub main()
devi@0 72 {
devi@0 73 binmode STDOUT, ":utf8";
devi@0 74
devi@0 75 if (! @ARGV) {
devi@0 76 print_usage_info();
devi@0 77 exit(0);
devi@0 78 }
devi@0 79
devi@0 80 load_config;
devi@0 81 load_run;
devi@0 82 load_scripts;
devi@0 83 load_class;
devi@0 84 load_course;
devi@0 85
devi@0 86 my $arg = join " ", @ARGV;
devi@0 87
devi@0 88 # Getting @SelectedMachines if any
devi@0 89 if ($arg =~ s/@(.*?)\s//) {
devi@0 90 my $machines = $1;
devi@0 91 my @list = split /,/, $machines;
devi@0 92 for my $interval (@list) {
devi@0 93 my ($first, $last) = split /-/, $interval;
devi@0 94
devi@0 95 push @SelectedMachines, $first;
devi@0 96 while ($first < $last) {
devi@0 97 push @SelectedMachines, ++$first;
devi@0 98 }
devi@0 99 }
devi@0 100 }
devi@0 101
devi@0 102 # Choose command to do
devi@0 103 switch ($arg) {
devi@0 104 case "next" { lm_next }
devi@0 105 case "prev" { lm_prev }
devi@0 106 case /set / { $arg =~ /set (.*)/; lm_set $1 }
devi@0 107 case "report" { lm_report }
devi@0 108 case "start" { lm_start }
devi@0 109 case "stop" { lm_stop }
devi@0 110 case "show hosts" { lm_show_hosts }
devi@0 111 case "show labs" { lm_show_labs }
devi@0 112 case /do / { $arg =~ /do (.*)/; lm_do "$1" }
devi@0 113 else { print_usage_info() }
devi@0 114 }
devi@0 115 save_run;
devi@0 116 exit(0);
devi@0 117 }
devi@0 118
devi@0 119 sub load_scripts
devi@0 120 {
devi@0 121 local $/;
devi@0 122 $_=<SCRIPTS>;
devi@0 123 %Scripts = ("empty-element", split (/###(.*)\n/));
devi@0 124 delete($Scripts{"empty-element"});
devi@0 125 }
devi@0 126
devi@0 127 sub load_config
devi@0 128 {
devi@0 129 my %file_config;
devi@0 130 my %argv_config;
devi@0 131 #read_config_file(\%file_config, $Config_File);
devi@0 132 GetOptions(\%argv_config, map "$_=s", keys %Config);
devi@0 133 %Config = (%Config, %file_config, %argv_config);
devi@0 134 }
devi@0 135
devi@0 136 sub load_course
devi@0 137 {
devi@0 138 $XMLCourse = XMLin($Config{"courses_path"}.$XMLClass->{"course"}.".xml", ForceArray => 1 )
devi@0 139 or die "Can't open file of the course ",$XMLClass->{"course"}," [with .xml extension]\n";
devi@0 140 # print Dumper($XMLCourse);
devi@0 141 for my $lab (@{$XMLCourse->{"module"}}) {
devi@0 142 push @Labs, $lab->{"code"};
devi@0 143 }
devi@0 144 }
devi@0 145
devi@0 146 sub load_class
devi@0 147 {
devi@0 148 my $classfile =
devi@0 149 $Config{"path_classes"}."/".$Config{"class"}.$Config{"class_suffix"};
devi@0 150 $XMLClass = XMLin($classfile , ForceArray => [ 'student' ] )
devi@0 151 or die "Can't open file of the class ",$classfile,"\n";
devi@0 152
devi@0 153 for my $student (@{$XMLClass->{"student"}}) {
devi@0 154 $Machines{$student->{"host"}} = {
devi@0 155 "name" => "$student->{firstname} $student->{surname}",
devi@0 156 "user" => "$student->{user}",
devi@0 157 "student" => $student,
devi@0 158 }
devi@0 159 }
devi@0 160 # print Dumper($XMLClass);
devi@0 161 # print Dumper(\%Machines);
devi@0 162 }
devi@0 163
devi@0 164
devi@0 165 sub lm_next
devi@0 166 {
devi@0 167 for(my $i=0; $i<=$#Labs; $i++){
devi@0 168 if ( $Labs[$i] eq $Run{"lab"} ) {
devi@0 169 if ($i < $#Labs) {
devi@0 170 lm_set($Labs[$i+1]);
devi@0 171 return ;
devi@0 172 } else {
devi@0 173 die "Lab ", $Run{"lab"}, " is the last. Switch to next lab is impossible"
devi@0 174 }
devi@0 175 }
devi@0 176
devi@0 177 }
devi@0 178 die "Lab ", $Run{"lab"}, " not found. Don't know which is next"
devi@0 179 }
devi@0 180
devi@0 181 sub lm_prev
devi@0 182 # Switch to previous lab
devi@0 183 {
devi@0 184 for(my $i=0; $i<=$#Labs; $i++){
devi@0 185 if ( $Labs[$i] eq $Run{"lab"} ) {
devi@0 186 if ($i > 0) {
devi@0 187 lm_set($Labs[$i-1]);
devi@0 188 return ;
devi@0 189 } else {
devi@0 190 die "Lab ", $Run{"lab"}, " is the first. Switch to previous lab is impossible"
devi@0 191 }
devi@0 192 }
devi@0 193
devi@0 194 }
devi@0 195 die "Lab ", $Run{"lab"}, " not found. Don't know which is previous"
devi@0 196 }
devi@0 197
devi@0 198 sub lm_set
devi@0 199 # Switch to $_[0] lab
devi@0 200 # FIXME
devi@0 201 {
devi@0 202 my $lab = shift;
devi@0 203 print "Current lab is $lab\n";
devi@0 204 $Run{"lab"} = "$lab";
devi@0 205 lm_do "setlab", $lab;
devi@0 206 }
devi@0 207
devi@0 208
devi@0 209 sub lm_start
devi@0 210 # Start new training day
devi@0 211 {
devi@0 212 print_log(`date`." STARTED\n");
devi@0 213 if ($Run{"lab"}) {
devi@0 214 lm_next;
devi@0 215 }
devi@0 216 else
devi@0 217 {
devi@0 218 # First lab in the course
devi@0 219 lm_set($Labs[0]);
devi@0 220 }
devi@0 221 }
devi@0 222
devi@0 223 sub lm_stop
devi@0 224 # Stop this training day
devi@0 225 {
devi@0 226 print_log(`date`." STOPPED\n");
devi@0 227 }
devi@0 228
devi@0 229
devi@0 230 sub lm_show_hosts
devi@0 231 # Show hosts used to run a commands
devi@0 232 {
devi@0 233 my $i=1;
devi@0 234 for my $m (sort keys %Machines) {
devi@0 235 if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) {
devi@0 236 print "($i)","\t",$m,"\t",$Machines{$m}->{"name"},"\n";
devi@0 237 }
devi@0 238 $i++;
devi@0 239 }
devi@0 240 }
devi@0 241
devi@0 242 sub lm_show_labs
devi@0 243 # Show hosts used to run a commands
devi@0 244 {
devi@0 245 my $i=1;
devi@0 246 for my $lab (@Labs) {
devi@0 247 print $lab;
devi@0 248 print "*" if $lab eq $Run{"lab"};
devi@0 249 print "\n";
devi@0 250 }
devi@0 251 }
devi@0 252
devi@0 253 sub lm_do
devi@0 254 # Do the $_[0] command on all of the hosts
devi@0 255 {
devi@0 256 my $command = shift;
devi@0 257 my $arg = join " ", @_;
devi@0 258 my $i=1;
devi@0 259 for my $m (sort keys %Machines) {
devi@0 260 if (!@SelectedMachines || grep $_ eq $i, @SelectedMachines) {
devi@0 261 print "$m:\n" if $Config{"show_host"} =~ /y/i;
devi@0 262
devi@0 263 my %myenv = ( %Config,
devi@0 264 host => $m,
devi@0 265 dirs => "/root /home/".$Machines{$m}->{"user"},
devi@0 266 lablogs => $Config{"lablogs_path"}."/".
devi@0 267 $XMLClass->{"course"}."/".
devi@0 268 $XMLClass->{"date"}."/".
devi@0 269 "$m",
devi@0 270 lab => $arg,
devi@0 271
devi@0 272 email => $Machines{$m}->{"student"}->{"email"},
devi@0 273 company => $Machines{$m}->{"student"}->{"company"},
devi@0 274 center => $XMLClass->{"center"},
devi@0 275 course => $XMLClass->{"course"},
devi@0 276 date => $XMLClass->{"date"},
devi@0 277 name => $Machines{$m}->{"name"},
devi@0 278 coursepath => $XMLCourse->{"path"},
devi@0 279
devi@0 280 );
devi@0 281 if (grep { $_ eq $command} keys %Scripts) {
devi@0 282 $_=$Scripts{"$command"};
devi@0 283 s/\$(\w+)/$myenv{$1}/ge;
devi@0 284 open(SHELL, "|/bin/sh -s");
devi@0 285 binmode SHELL, ":utf8";
devi@0 286 print SHELL $_;
devi@0 287 close (SHELL);
devi@0 288 }
devi@0 289 else {
devi@0 290 my $res = `ssh $Config{"ssh_user"}\@$m $command`;
devi@0 291 if ($res) {
devi@0 292 my $count = ($res =~ s/(^)/$m: /mg);
devi@0 293 print $res;
devi@0 294 print "\n" if ($count > 1);
devi@0 295 }
devi@0 296 }
devi@0 297 }
devi@0 298 $i++;
devi@0 299 }
devi@0 300 }
devi@0 301
devi@0 302
devi@0 303 sub lm_report
devi@0 304 {
devi@0 305
devi@0 306 print "Not implemented yet\n";
devi@0 307 exit(1);
devi@0 308
devi@0 309 =cut comment
devi@0 310
devi@0 311 Дальше идут скрипты, код которых нужно реализовать здесь.
devi@0 312 Как минимум.
devi@0 313
devi@0 314 =cut
devi@0 315
devi@0 316 my $lm_script_make_report_web = <<'SCRIPT';
devi@0 317
devi@0 318 #!/bin/sh
devi@0 319
devi@0 320 ####cd /home/devi/lm
devi@0 321 ./lm do copy-lablogs
devi@0 322 ##./lm-report --input /home/murk/.labmaker --output /var/www/lm/murk.html
devi@0 323 ##exit
devi@0 324
devi@0 325 COURSE=ug-h
devi@0 326 DATE=2005-04-25
devi@0 327 SUFF=".linux.nt"
devi@0 328 #MACHINES="m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15"
devi@0 329 #MACHINES="m1 m2 m3 m4 m5 m6 m7 f1 f2 f3 f4 f5"
devi@0 330 MACHINES="m01 m02 m03 m04 m05 m06 m07 m08"
devi@0 331 #MACHINES="m1"
devi@0 332 USERS="user root"
devi@0 333 WEBDIR=/var/www/lm
devi@0 334
devi@0 335 for u in $USERS
devi@0 336 do
devi@0 337 for m in $MACHINES
devi@0 338 do
devi@0 339 e=utf-8
devi@0 340 [ "${m##f}" = "$m" ] || e=koi8-r
devi@0 341 #e=koi8-r
devi@0 342 mkdir -p $WEBDIR/$DATE/$m
devi@0 343 cp share/*.ico share/*.css $WEBDIR/$m
devi@0 344 #echo Processing Lablogs/$COURSE/$DATE/$m$SUFF/$u/
devi@0 345 ./lm-report\
devi@0 346 --input Lablogs/$COURSE/$DATE/$m$SUFF/$u/ \
devi@0 347 --diffs "Lablogs/$COURSE/$DATE/$m$SUFF/$u/ Lablogs/$COURSE/$DATE/$m$SUFF/root/"\
devi@0 348 --output /var/www/lm/$DATE/$m/$u.html \
devi@0 349 --encoding $e
devi@0 350 done
devi@0 351 done
devi@0 352
devi@0 353
devi@0 354 SCRIPT
devi@0 355
devi@0 356 my $lm_script_make_report_all = <<'SCRIPT';
devi@0 357
devi@0 358 #!/bin/sh
devi@0 359 WEBDIR=/var/www/lm
devi@0 360
devi@0 361 find . -type d -maxdepth 5 -mindepth 5 |\
devi@0 362 while read dir
devi@0 363 do
devi@0 364 subdir=${dir##Lablogs/}
devi@0 365 e=utf-8
devi@0 366 echo $dir | grep -qi bsd && e=koi8-r
devi@0 367 echo $dir | grep -qi /f && e=koi8-r
devi@0 368
devi@0 369 mkdir -p $WEBDIR/${subdir%/*}
devi@0 370 cp share/*.ico share/*.css $WEBDIR/${subdir%/*}
devi@0 371 #echo Processing Lablogs/$COURSE/$DATE/$m$SUFF/$u/
devi@0 372 ./lm-report\
devi@0 373 --input $dir \
devi@0 374 --diffs "${dir%/user}/root $dir"\
devi@0 375 --output $WEBDIR/$subdir.html \
devi@0 376 --encoding $e
devi@0 377 done
devi@0 378
devi@0 379 SCRIPT
devi@0 380 }
devi@0 381
devi@0 382 sub load_run
devi@0 383 {
devi@0 384 my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"};
devi@0 385 open (RUN, $runfile)
devi@0 386 or return;
devi@0 387 while (<RUN>) {
devi@0 388 chomp;
devi@0 389 my ($var, $val) = split /\s+/,$_,2;
devi@0 390 $Run{$var}=$val;
devi@0 391 }
devi@0 392 close (RUN);
devi@0 393 }
devi@0 394
devi@0 395 sub save_run
devi@0 396 {
devi@0 397 my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"};
devi@0 398 open (RN, "$runfile")
devi@0 399 or die "Can't save running state to $runfile";
devi@0 400 for my $var (keys %Run) {
devi@0 401 print RN $var,"\t",$Run{$var},"\n";
devi@0 402 }
devi@0 403 close (RN);
devi@0 404 }
devi@0 405
devi@0 406 sub print_log
devi@0 407 {
devi@0 408 my $logfile = $Config{"path_labmaker"}."/".$Config{"path_logfile"};
devi@0 409 open (LOG, ">>$logfile")
devi@0 410 or die "Can't open logfile $logfile for writing";
devi@0 411 print LOG @_;
devi@0 412 close (LOG);
devi@0 413 }
devi@0 414
devi@0 415
devi@0 416 sub print_usage_info
devi@0 417 {
devi@0 418 print "Usage:\n\n\t$0 [host-list] command\n";
devi@0 419 while (<USAGE>) {
devi@0 420 print $_;
devi@0 421 }
devi@0 422 }
devi@0 423
devi@0 424 __USAGE__
devi@0 425
devi@0 426 Commands:
devi@0 427
devi@0 428 next -- next lab
devi@0 429 prev -- prev lab
devi@0 430 set LAB -- set current lab to LAB
devi@0 431 start -- start this day training
devi@0 432 stop -- stop this day training
devi@0 433 show hosts -- show available hosts in the class
devi@0 434 show labs -- show available labs in the course
devi@0 435 do COMMAND -- do specified command on the hosts of hostlist
devi@0 436 report -- generate XML/HTML reports
devi@0 437
devi@0 438
devi@0 439 do commands:
devi@0 440
devi@0 441 install [PROFILE] -- install profile
devi@0 442
devi@0 443 Host list:
devi@0 444
devi@0 445 @N -- machine N
devi@0 446 @N1-N2 -- all of the machines from N1 to N2
devi@0 447 @N1,N2,N3 -- machine N1, N2 and N3
devi@0 448
devi@0 449 N* is numbers or domain names of the machines.
devi@0 450
devi@0 451 If host list is not specified,
devi@0 452 command is executed on all of the machines
devi@0 453
devi@0 454
devi@0 455
devi@0 456 __SCRIPTS__
devi@0 457 ###install
devi@0 458 cat $sshkey | $lmssh $ssh_user@$host /bin/sh -c '"mkdir -p ~/.ssh; cat >>~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys"'
devi@0 459
devi@0 460 ###install-lm
devi@0 461 cat $lminstall | ssh $ssh_user@$host /bin/sh -s $dirs
devi@0 462
devi@0 463 ###copy-lablogs
devi@0 464 for i in $dirs
devi@0 465 do
devi@0 466 mkdir -p $lablogs/${i##*/}
devi@0 467 scp -q $ssh_user@$host:${i}/.labmaker/* $lablogs/${i##*/}
devi@0 468 done
devi@0 469
devi@0 470 ###setlab
devi@0 471 for i in $dirs
devi@0 472 do
devi@0 473 echo $lab | ssh $ssh_user@$host "cat > "${i}"/.labmaker/lab"
devi@0 474 done
devi@0 475
devi@0 476 ###makeout
devi@0 477 common=$course-$date
devi@0 478 personal=$course-$date-$email
devi@0 479 mkdir -p $outpath/${common}/{Lablogs,Docs}
devi@0 480 mkdir -p $outpath/${personal}/{Course,Files}
devi@0 481 cd $outpath/${personal}
devi@0 482 ln -s ../${common}/Lablogs .
devi@0 483 ln -s ../${common}/Docs .
devi@0 484 cd ~-
devi@0 485 export UG_PERSONAL=${PWD}/$outpath/${personal}/Course
devi@0 486 export UG_CENTER="$center"
devi@0 487 export UG_COURSE="$course"
devi@0 488 export UG_DATE="$date"
devi@0 489 export UG_STUDENT="$name"
devi@0 490 export UG_COMPANY="$company"
devi@0 491 cd $coursepath; make personal; cd ~-
devi@0 492
devi@0 493 ###watch
devi@0 494 cat taillast.pl | ssh $ssh_user@$host perl - /root/.labmaker