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