lilalo

view lm @ 100:2c00c61f2d7b

Коммичу изменения, но сам не знаю зачем.
Нужно 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 }