lilalo

annotate lm @ 92:db51b62442ac

Написан прототип lm get
author devi
date Sat Apr 22 17:08:05 2006 +0300 (2006-04-22)
parents 1e1422588716
children 45196265d30e
rev   line source
devi@0 1 #!/usr/bin/perl
devi@0 2
devi@0 3
devi@0 4 use strict;
devi@0 5 use Data::Dumper;
devi@0 6 use Switch;
devi@0 7 use XML::Simple;
devi@0 8 use Getopt::Long;
devi@4 9 use utf8;
devi@0 10
devi@40 11 use lib "/usr/local/bin";
devi@40 12 use l3config;
devi@40 13
devi@0 14 our $XMLClass;
devi@0 15 our $XMLCourse;
devi@0 16 our @Labs;
devi@0 17
devi@92 18 our %Machines; # Machines list from class.xml
devi@92 19 our @SelectedMachines; # Machines list given as the command line argument
devi@0 20
devi@0 21 our $Config_File = "labmaker.conf";
devi@40 22 our %Config_ = (
devi@92 23 "show_host" => "no",
devi@0 24
devi@92 25 # Вспомогательные программы
devi@92 26 #"l3-report" => "./lm-report",
devi@92 27 "l3-report" => "./l3-report",
devi@3 28
devi@92 29 # Каталоги
devi@92 30 "path_lilalo" => "/var/lilalo/",
devi@92 31 "path_classes" => "/var/lilalo/classes/",
devi@92 32 "path_lablogs" => "/var/lilalo/lablogs/",
devi@92 33 "courses_path" => "/var/lilalo/courses/",
devi@92 34 "outpath" => "/var/lilalo/out/",
devi@92 35 "path_web" => "/var/www/l3", # Путь к web-отчётам
devi@92 36 "path_share" => "./share/", # Путь к web-отчётам
devi@0 37
devi@92 38 # Файлы
devi@92 39 "runfile" => "lm.run",
devi@92 40 "logfile" => "lm.log",
devi@0 41
devi@92 42 "class" => "class", # Имя файла класса
devi@92 43 "class_suffix" => ".xml", # Cуффикс файла класса
devi@92 44 "classfile" => "",
devi@0 45
devi@92 46 "sshkey" => "$ENV{HOME}/.ssh/id_dsa.pub",
devi@92 47 "lmssh" => "./lm-ssh",
devi@92 48 "lminstall" => "./lm-install",
devi@92 49 "ssh_user" => "root",
devi@0 50 );
devi@0 51
devi@0 52 our %Run = (
devi@92 53 "lab" => ""
devi@0 54 );
devi@0 55
devi@0 56 our %Scripts;
devi@0 57
devi@0 58 sub load_class;
devi@0 59 sub load_config;
devi@0 60 sub load_course;
devi@0 61 sub load_scripts;
devi@0 62
devi@92 63 sub lm_get;
devi@0 64 sub lm_next;
devi@0 65 sub lm_prev;
devi@0 66 sub lm_start;
devi@0 67 sub lm_stop;
devi@0 68 sub lm_set;
devi@0 69 sub lm_do;
devi@0 70 sub lm_report;
devi@0 71 sub lm_show_hosts;
devi@69 72 sub lm_show_email;
devi@0 73 sub lm_show_labs;
devi@0 74
devi@0 75 sub load_run;
devi@0 76 sub save_run;
devi@0 77 sub print_log;
devi@0 78 sub print_usage_info;
devi@0 79 sub main();
devi@0 80
devi@0 81 main();
devi@0 82
devi@0 83 sub main()
devi@0 84 {
devi@92 85 binmode STDOUT, ":utf8";
devi@0 86
devi@92 87 if (! @ARGV) {
devi@92 88 print_usage_info();
devi@92 89 exit(0);
devi@92 90 }
devi@0 91
devi@92 92 if ($ARGV[0] eq "get") {
devi@92 93 print "argv= ".$ARGV[0]."ZLO\n";
devi@92 94 lm_get;
devi@92 95 exit(0);
devi@92 96 }
devi@0 97
devi@92 98 init_config();
devi@92 99 #load_config;
devi@92 100 load_run;
devi@92 101 load_scripts;
devi@92 102 load_class;
devi@92 103 load_course;
devi@92 104
devi@92 105 my $arg = join " ", @ARGV;
devi@0 106
devi@92 107 # Getting @SelectedMachines if any
devi@92 108 if ($arg =~ s/@(.*?)\s//) {
devi@92 109 my $machines = $1;
devi@92 110 my @list = split /,/, $machines;
devi@92 111 for my $interval (@list) {
devi@92 112 my ($first, $last) = split /-/, $interval;
devi@0 113
devi@92 114 push @SelectedMachines, $first;
devi@92 115 while ($first < $last) {
devi@92 116 push @SelectedMachines, ++$first;
devi@92 117 }
devi@92 118 }
devi@92 119 }
devi@92 120
devi@92 121 # Choose command to do
devi@92 122 switch ($arg) {
devi@92 123 case "next" { lm_next }
devi@92 124 case "prev" { lm_prev }
devi@92 125 case /set / { $arg =~ /set (.*)/; lm_set $1 }
devi@92 126 case "report" { lm_report }
devi@92 127 case "start" { lm_start }
devi@92 128 case "stop" { lm_stop }
devi@92 129 case "show hosts" { lm_show_hosts }
devi@92 130 case "show email" { lm_show_email }
devi@92 131 case "show labs" { lm_show_labs }
devi@92 132 case /do / { $arg =~ /do (.*)/; lm_do "$1" }
devi@92 133 else { print_usage_info() }
devi@92 134 }
devi@92 135 save_run;
devi@92 136 exit(0);
devi@0 137 }
devi@0 138
devi@0 139 sub load_scripts
devi@0 140 {
devi@92 141 open (SCRIPTS, "$Config{l3scripts}")
devi@92 142 or die "Cant open l3scripts file: ".$Config{l3scripts}.": $!\n";
devi@92 143 binmode SCRIPTS, ":utf8";
devi@92 144 local $/;
devi@92 145 $_=<SCRIPTS>;
devi@92 146 close(SCRIPTS);
devi@40 147
devi@92 148 %Scripts = ("empty-element", split (/###(.*)\n/));
devi@92 149 delete($Scripts{"empty-element"});
devi@40 150
devi@0 151 }
devi@0 152
devi@0 153 sub load_config
devi@0 154 {
devi@92 155 my %file_config;
devi@92 156 my %argv_config;
devi@92 157 #read_config_file(\%file_config, $Config_File);
devi@92 158 GetOptions(\%argv_config, map "$_=s", keys %Config);
devi@92 159 %Config = (%Config, %file_config, %argv_config);
devi@0 160 }
devi@0 161
devi@0 162 sub load_course
devi@0 163 {
devi@92 164 $XMLCourse = XMLin($Config{"courses_path"}.$XMLClass->{"course"}.".xml", ForceArray => 1 )
devi@92 165 or die "Can't open file of the course ",$XMLClass->{"course"}," [with .xml extension]\n";
devi@92 166 # print Dumper($XMLCourse);
devi@92 167 for my $lab (@{$XMLCourse->{"module"}}) {
devi@92 168 push @Labs, $lab->{"code"};
devi@92 169 }
devi@0 170 }
devi@0 171
devi@0 172 sub load_class
devi@0 173 {
devi@92 174 my $classfile =
devi@92 175 $Config{"classfile"} ||
devi@92 176 $Config{"path_classes"}."/".$Config{"class"}.$Config{"class_suffix"};
devi@92 177 $XMLClass = XMLin($classfile , ForceArray => [ 'student' ] )
devi@92 178 or die "Can't open file of the class ",$classfile,"\n";
devi@0 179
devi@92 180 for my $student (@{$XMLClass->{"student"}}) {
devi@92 181 $Machines{$student->{"host"}} = {
devi@92 182 "name" => "$student->{firstname} $student->{surname}",
devi@92 183 "firstname" => "$student->{firstname}",
devi@92 184 "user" => "$student->{user}",
devi@92 185 "email" => "$student->{email}",
devi@92 186 "student" => $student,
devi@92 187 }
devi@92 188 }
devi@92 189 # print Dumper($XMLClass);
devi@92 190 # print Dumper(\%Machines);
devi@92 191 }
devi@92 192
devi@92 193 sub lm_get
devi@92 194 {
devi@92 195 print "Getting class description file...";
devi@92 196 if (system("cd $Config{path_classes}; wget -r xgu.ru/l3/classes/class.xml") ==0 )
devi@92 197 {
devi@92 198 print "Ok\n";
devi@92 199 }
devi@92 200 else {
devi@92 201 die "Can't load class file\n"
devi@92 202 }
devi@0 203 }
devi@0 204
devi@0 205
devi@0 206 sub lm_next
devi@0 207 {
devi@92 208 for(my $i=0; $i<=$#Labs; $i++){
devi@92 209 if ( $Labs[$i] eq $Run{"lab"} ) {
devi@92 210 if ($i < $#Labs) {
devi@92 211 lm_set($Labs[$i+1]);
devi@92 212 return ;
devi@92 213 } else {
devi@92 214 die "Lab ", $Run{"lab"}, " is the last. Switch to next lab is impossible"
devi@92 215 }
devi@92 216 }
devi@92 217
devi@92 218 }
devi@92 219 die "Lab ", $Run{"lab"}, " not found. Don't know which is next"
devi@0 220 }
devi@0 221
devi@0 222 sub lm_prev
devi@0 223 # Switch to previous lab
devi@0 224 {
devi@92 225 for(my $i=0; $i<=$#Labs; $i++){
devi@92 226 if ( $Labs[$i] eq $Run{"lab"} ) {
devi@92 227 if ($i > 0) {
devi@92 228 lm_set($Labs[$i-1]);
devi@92 229 return ;
devi@92 230 } else {
devi@92 231 die "Lab ", $Run{"lab"}, " is the first. Switch to previous lab is impossible"
devi@92 232 }
devi@92 233 }
devi@92 234
devi@92 235 }
devi@92 236 die "Lab ", $Run{"lab"}, " not found. Don't know which is previous"
devi@0 237 }
devi@0 238
devi@0 239 sub lm_set
devi@0 240 # Switch to $_[0] lab
devi@0 241 # FIXME
devi@0 242 {
devi@92 243 my $lab = shift;
devi@92 244 print "Current lab is $lab\n";
devi@92 245 $Run{"lab"} = "$lab";
devi@92 246 lm_do "setlab", $lab;
devi@0 247 }
devi@0 248
devi@0 249
devi@0 250 sub lm_start
devi@0 251 # Start new training day
devi@0 252 {
devi@92 253 print_log(`date`." STARTED\n");
devi@92 254 if ($Run{"lab"}) {
devi@92 255 lm_next;
devi@92 256 }
devi@92 257 else
devi@92 258 {
devi@92 259 # First lab in the course
devi@92 260 lm_set($Labs[0]);
devi@92 261 }
devi@0 262 }
devi@0 263
devi@0 264 sub lm_stop
devi@0 265 # Stop this training day
devi@0 266 {
devi@92 267 print_log(`date`." STOPPED\n");
devi@0 268 }
devi@0 269
devi@0 270
devi@0 271 sub lm_show_hosts
devi@0 272 # Show hosts used to run a commands
devi@0 273 {
devi@92 274 my $i=1;
devi@92 275 for my $m (sort keys %Machines) {
devi@92 276 if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) {
devi@92 277 print "($i)","\t",$m,"\t",$Machines{$m}->{"name"},"\n";
devi@92 278 }
devi@92 279 $i++;
devi@92 280 }
devi@0 281 }
devi@0 282
devi@69 283 sub lm_show_email
devi@69 284 # Show hosts used to run a commands
devi@69 285 {
devi@92 286 my $i=1;
devi@92 287 for my $m (sort keys %Machines) {
devi@92 288 if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) {
devi@92 289 print $Machines{$m}->{"email"},"\t",$Machines{$m}->{"name"},"\n";
devi@92 290 }
devi@92 291 $i++;
devi@92 292 }
devi@69 293 }
devi@69 294
devi@0 295 sub lm_show_labs
devi@0 296 # Show hosts used to run a commands
devi@0 297 {
devi@92 298 my $i=1;
devi@92 299 for my $lab (@Labs) {
devi@92 300 print $lab;
devi@92 301 print "*" if $lab eq $Run{"lab"};
devi@92 302 print "\n";
devi@92 303 }
devi@0 304 }
devi@0 305
devi@0 306 sub lm_do
devi@0 307 # Do the $_[0] command on all of the hosts
devi@0 308 {
devi@92 309 my $command = shift;
devi@92 310 my $arg = join " ", @_;
devi@92 311 my $i=1;
devi@40 312
devi@92 313 my %myenv = ( %Config,
devi@92 314 lab => $arg,
devi@92 315 center => $XMLClass->{"center"},
devi@92 316 course => $XMLClass->{"course"},
devi@92 317 date => $XMLClass->{"date"},
devi@92 318 stopdate => $XMLClass->{"stop-date"},
devi@92 319 instructor => $XMLClass->{"instructor"}->{"firstname"}." ".$XMLClass->{"instructor"}->{"surname"},
devi@92 320 manager => $XMLClass->{"manager"}->{"firstname"}." ".$XMLClass->{"manager"}->{"surname"},
devi@92 321 coursepath => $XMLCourse->{"path"},
devi@92 322 );
devi@40 323
devi@92 324 if (grep { $_ eq "PRE-$command"} keys %Scripts) {
devi@92 325 $_=$Scripts{"PRE-$command"};
devi@92 326 s/\$(\w+)/$myenv{$1}/ge;
devi@92 327 open(SHELL, "|/bin/sh -s");
devi@92 328 binmode SHELL, ":utf8";
devi@92 329 print SHELL $_;
devi@92 330 close (SHELL);
devi@92 331 }
devi@40 332
devi@40 333
devi@92 334 for my $m (sort keys %Machines) {
devi@92 335 if (!@SelectedMachines || grep $_ eq $i, @SelectedMachines) {
devi@92 336 print "$m:\n" if $Config{"show_host"} =~ /y/i;
devi@0 337
devi@92 338 %myenv = ( %myenv,
devi@92 339 host => $m,
devi@92 340 ipaddress => $Machines{$m}->{"ipaddress"},
devi@92 341 dirs => "/root /home/".$Machines{$m}->{"user"},
devi@92 342 lablogs => $Config{"path_lablogs"}."/".
devi@92 343 $XMLClass->{"course"}."/".
devi@92 344 $XMLClass->{"date"}."/".
devi@92 345 "$m",
devi@92 346 email => $Machines{$m}->{"student"}->{"email"},
devi@92 347 company => $Machines{$m}->{"student"}->{"company"},
devi@92 348 name => $Machines{$m}->{"name"},
devi@92 349 firstname => $Machines{$m}->{"firstname"},
devi@92 350 );
devi@92 351 if (grep { $_ eq $command} keys %Scripts) {
devi@92 352 $_=$Scripts{"$command"};
devi@92 353 s/\$(\w+)/$myenv{$1}/ge;
devi@92 354 open(SHELL, "|/bin/sh -s");
devi@92 355 binmode SHELL, ":utf8";
devi@92 356 print SHELL $_;
devi@92 357 close (SHELL);
devi@92 358 }
devi@92 359 else {
devi@92 360 my $res = `ssh $Config{"ssh_user"}\@$m $command`;
devi@92 361 if ($res) {
devi@92 362 my $count = ($res =~ s/(^)/$m: /mg);
devi@92 363 print $res;
devi@92 364 print "\n" if ($count > 1);
devi@92 365 }
devi@92 366 }
devi@92 367 }
devi@92 368 $i++;
devi@92 369 }
devi@40 370
devi@92 371 if (grep { $_ eq "POST-$command"} keys %Scripts) {
devi@92 372 $_=$Scripts{"POST-$command"};
devi@92 373 s/\$(\w+)/$myenv{$1}/ge;
devi@92 374 open(SHELL, "|/bin/sh -s");
devi@92 375 binmode SHELL, ":utf8";
devi@92 376 print SHELL $_;
devi@92 377 close (SHELL);
devi@92 378 }
devi@0 379 }
devi@0 380
devi@0 381
devi@3 382
devi@3 383 =cut comment
devi@3 384
devi@3 385 lm report
devi@3 386
devi@3 387 Построить html представление для журналов текущего класса.
devi@3 388 Для построения используется скрипт l3-report.
devi@3 389
devi@3 390 =cut
devi@3 391
devi@0 392 sub lm_report
devi@0 393 {
devi@0 394
devi@92 395 my $webdir = $Config{"path_web"};
devi@92 396 my $course=$XMLClass->{"course"};
devi@92 397 my $date=$XMLClass->{"date"};
devi@92 398 my $encoding=$XMLClass->{"charset"};
devi@0 399
devi@92 400 my $center = $XMLClass->{"center"};
devi@92 401 my $instructor = $XMLClass->{"instructor"}->{"firstname"}." ".$XMLClass->{"instructor"}->{"surname"};
devi@92 402 my $course_name = $XMLCourse->{"fullname"}[0];
devi@4 403
devi@5 404
devi@92 405 # Собственно журналы
devi@5 406
devi@92 407 for my $student (@{$XMLClass->{"student"}}) {
devi@92 408 my $user = $student->{"user"};
devi@92 409 my $hostname = $student->{"host"};
devi@92 410 my $encoding = $student->{"charset"};
devi@92 411 my $student_name = $student->{"firstname"}." ".$student->{"surname"};
devi@5 412
devi@92 413 system("mkdir -p $webdir/$date/$hostname");
devi@92 414 system("cp ".$Config{"path_share"}."/*.{ico,css} $webdir/$date/$hostname");
devi@92 415 system($Config{"l3-report"}.
devi@92 416 " --input ".$Config{"path_lablogs"}."/$course/$date/$hostname/$user".
devi@92 417 " --diffs ".$Config{"path_lablogs"}."/$course/$date/$hostname/$user ".
devi@92 418 $Config{"path_lablogs"}."/$course/$date/$hostname/root".
devi@92 419 " --output $webdir/$date/$hostname/$user.html".
devi@92 420 " --course-name '$course_name'".
devi@92 421 " --course-code '$course'".
devi@92 422 " --course-date '$date'".
devi@92 423 " --course-center '$center'".
devi@92 424 " --course-student '$student_name'".
devi@92 425 " --course-trainer '$instructor'".
devi@92 426 " --encoding $encoding"
devi@92 427 );
devi@92 428 system($Config{"l3-report"}.
devi@92 429 " --input ".$Config{"path_lablogs"}."/$course/$date/$hostname/root".
devi@92 430 " --diffs ".$Config{"path_lablogs"}."/$course/$date/$hostname/root ".
devi@92 431 " --output $webdir/$date/$hostname/root.html".
devi@92 432 " --course-name '$course_name'".
devi@92 433 " --course-code '$course'".
devi@92 434 " --course-date '$date'".
devi@92 435 " --course-center '$center'".
devi@92 436 " --course-student '$student_name'".
devi@92 437 " --course-trainer '$instructor'".
devi@92 438 " --encoding $encoding"
devi@92 439 );
devi@92 440 }
devi@5 441
devi@92 442 # Индекс для данного класса
devi@4 443
devi@92 444 my $head;
devi@4 445
devi@92 446 $head="Журналы лабораторных работ";
devi@92 447 open(HTML, ">$webdir/$date/index.html")
devi@92 448 or die "Can't open $webdir/$date/index.html for writing";
devi@92 449 binmode HTML, ":utf8";
devi@92 450 print HTML <<HEAD;
devi@92 451 <html>
devi@92 452 <head>
devi@92 453 <meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
devi@92 454 <title>$head</title>
devi@92 455 </head>
devi@92 456 <body>
devi@92 457 <h1>$head</h1>
devi@92 458 <p>
devi@92 459 Курс: $course_name ($course)<br/>
devi@92 460 Начало: $date<br/>
devi@92 461 Учебный центр: $center <br/>
devi@92 462 Инструктор: $instructor <br/>
devi@92 463 </p>
devi@92 464 <table>
devi@4 465 HEAD
devi@92 466 for my $student (@{$XMLClass->{"student"}}) {
devi@92 467 my $user = $student->{"user"};
devi@92 468 my $hostname = $student->{"host"};
devi@92 469 print HTML "<tr>\n";
devi@92 470 print HTML "<td>",$student->{"firstname"}," ",$student->{"surname"},"</td>\n";
devi@92 471 print HTML "<td>",$hostname,"</td>\n";
devi@92 472 print HTML "<td><a href=\"$hostname/$user.html\">",$user,"</td>\n";
devi@92 473 print HTML "<td><a href=\"$hostname/root.html\">","root","</td>\n";
devi@92 474 print HTML "</tr>\n";
devi@92 475 }
devi@92 476 print HTML <<TAIL;
devi@92 477 </table>
devi@92 478 </html>
devi@4 479 TAIL
devi@92 480 close (HTML);
devi@4 481
devi@92 482
devi@92 483
devi@0 484 }
devi@0 485
devi@0 486 sub load_run
devi@0 487 {
devi@92 488 my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"};
devi@92 489 open (RUN, $runfile)
devi@92 490 or return;
devi@92 491 while (<RUN>) {
devi@92 492 chomp;
devi@92 493 my ($var, $val) = split /\s+/,$_,2;
devi@92 494 $Run{$var}=$val;
devi@92 495 }
devi@92 496 close (RUN);
devi@0 497 }
devi@0 498
devi@0 499 sub save_run
devi@0 500 {
devi@92 501 my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"};
devi@92 502 open (RN, "$runfile")
devi@92 503 or die "Can't save running state to $runfile";
devi@92 504 for my $var (keys %Run) {
devi@92 505 print RN $var,"\t",$Run{$var},"\n";
devi@92 506 }
devi@92 507 close (RN);
devi@0 508 }
devi@0 509
devi@0 510 sub print_log
devi@0 511 {
devi@92 512 my $logfile = $Config{"path_labmaker"}."/".$Config{"path_logfile"};
devi@92 513 open (LOG, ">>$logfile")
devi@92 514 or die "Can't open logfile $logfile for writing";
devi@92 515 print LOG @_;
devi@92 516 close (LOG);
devi@0 517 }
devi@0 518
devi@0 519
devi@0 520 sub print_usage_info
devi@0 521 {
devi@92 522 print "Usage:\n\n\t$0 [host-list] command\n";
devi@92 523 print <<'USAGE';
devi@0 524
devi@0 525 Commands:
devi@0 526
devi@92 527 next -- next lab
devi@92 528 prev -- prev lab
devi@92 529 set LAB -- set current lab to LAB
devi@92 530 start -- start this day training
devi@92 531 stop -- stop this day training
devi@92 532 show hosts -- show available hosts in the class
devi@92 533 show labs -- show available labs in the course
devi@92 534 do COMMAND -- do specified command on the hosts of hostlist
devi@92 535 report -- generate XML/HTML reports
devi@0 536
devi@92 537
devi@0 538 do commands:
devi@92 539
devi@92 540 install [PROFILE] -- install profile
devi@92 541
devi@92 542 Host list:
devi@0 543
devi@92 544 @N -- machine N
devi@92 545 @N1-N2 -- all of the machines from N1 to N2
devi@92 546 @N1,N2,N3 -- machine N1, N2 and N3
devi@0 547
devi@92 548 N* is numbers or domain names of the machines.
devi@92 549
devi@92 550 If host list is not specified,
devi@92 551 command is executed on all of the machines
devi@0 552
devi@40 553 USAGE
devi@40 554 }
devi@0 555
devi@0 556