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