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