| 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 
 |