lilalo
view lm @ 3:6c1d2b9f45e7
Добавил команду lm report.
Строит html-представление журналов
для заданного класса.
Нужно сделать поддержку опций GetOpt::Long
и тогда эту же команду можно будет использовать
для построения всех журналов в репозитории.
Строит html-представление журналов
для заданного класса.
Нужно сделать поддержку опций GetOpt::Long
и тогда эту же команду можно будет использовать
для построения всех журналов в репозитории.
| author | devi | 
|---|---|
| date | Tue May 24 13:00:28 2005 +0300 (2005-05-24) | 
| parents | 18b21f6918f0 | 
| children | 774de5c1ad00 | 
 line source
     1 #!/usr/bin/perl
     4 use strict;
     5 use Inline::Files;
     6 use Data::Dumper;
     7 use Switch;
     8 use XML::Simple;
     9 use Getopt::Long;
    11 our $XMLClass;
    12 our $XMLCourse;
    13 our @Labs;
    15 our %Machines;			# Machines list from class.xml
    16 our @SelectedMachines;		# Machines list given as the command line argument
    18 our $Config_File = "labmaker.conf";
    19 our %Config = (
    20 	"show_host" 	=> "no",
    22 	# Вспомогательные программы
    23 	"l3-report"	=> "./lm-report",
    25 	# Каталоги
    26 	"path_labmaker" => "/var/labmaker/",
    27 	"path_classes"	=> "/var/labmaker/classes/",
    28 	"path_lablogs"	=> "/var/labmaker/lablogs/",
    29 	"courses_path"	=> "/var/labmaker/courses/",
    30 	"outpath"	=> "/var/labmaker/out/",
    31 	"path_web"	=> "/var/www/l3",		# Путь к web-отчётам
    32 	"path_share"	=> "./share/",		# Путь к web-отчётам
    34 	# Файлы
    35 	"runfile"	=> "lm.run", 
    36 	"logfile"	=> "lm.log", 
    38 	"class" 	=> "class", 				# Имя файла класса
    39 	"class_suffix" 	=> ".xml", 				# Cуффикс файла класса
    41 	"sshkey"	=> "$ENV{HOME}/.ssh/id_dsa.pub",
    42 	"lmssh"		=> "./lm-ssh",
    43 	"lminstall"	=> "./lm-install",
    44 	"ssh_user"	=> "r",
    45 );
    47 our %Run = (
    48 	"lab" => ""
    49 );
    51 our %Scripts;
    53 sub load_class;
    54 sub load_config;
    55 sub load_course;
    56 sub load_scripts;
    58 sub lm_next;
    59 sub lm_prev;
    60 sub lm_start;
    61 sub lm_stop;
    62 sub lm_set;
    63 sub lm_do;
    64 sub lm_report;
    65 sub lm_show_hosts;
    66 sub lm_show_labs;
    68 sub load_run;
    69 sub save_run;
    70 sub print_log;
    71 sub print_usage_info;
    72 sub main();
    74 main();
    76 sub main()
    77 {
    78 	binmode STDOUT, ":utf8";
    80 	if (! @ARGV) {
    81 		print_usage_info();
    82 		exit(0);
    83 	}
    85 	load_config;
    86 	load_run;
    87 	load_scripts;
    88 	load_class;
    89 	load_course;
    91 	my $arg = join " ", @ARGV;
    93 	# Getting @SelectedMachines if any
    94 	if ($arg =~ s/@(.*?)\s//) {
    95 		my $machines = $1;
    96 		my @list = split /,/, $machines;
    97 		for my $interval (@list) {
    98 			my ($first, $last) = split /-/, $interval;
   100 			push @SelectedMachines, $first;
   101 			while ($first < $last) {
   102 				push @SelectedMachines, ++$first;
   103 			}	
   104 		}
   105 	}
   107 	# Choose command to do
   108 	switch ($arg) {
   109 		case "next"	{ lm_next }
   110 		case "prev"	{ lm_prev }
   111 		case /set /	{ $arg =~ /set (.*)/; lm_set $1 }
   112 		case "report"	{ lm_report }
   113 		case "start"	{ lm_start }
   114 		case "stop"	{ lm_stop }
   115 		case "show hosts" { lm_show_hosts }
   116 		case "show labs" { lm_show_labs }
   117 		case /do /  { $arg =~ /do (.*)/;  lm_do "$1" }
   118 		else 		{ print_usage_info() }
   119 	}
   120 	save_run;
   121 	exit(0);
   122 }
   124 sub load_scripts
   125 {
   126 	local $/;
   127 	$_=<SCRIPTS>;
   128 	%Scripts = ("empty-element", split (/###(.*)\n/));
   129 	delete($Scripts{"empty-element"});
   130 }
   132 sub load_config
   133 {
   134 	my %file_config;
   135 	my %argv_config;
   136 	#read_config_file(\%file_config, $Config_File);
   137 	GetOptions(\%argv_config, map "$_=s", keys %Config);
   138 	%Config = (%Config, %file_config, %argv_config);
   139 }
   141 sub load_course
   142 {
   143 	$XMLCourse = XMLin($Config{"courses_path"}.$XMLClass->{"course"}.".xml", ForceArray => 1 )  
   144 		or die "Can't open file of the course ",$XMLClass->{"course"}," [with .xml extension]\n";
   145 #	print Dumper($XMLCourse);
   146 	for my $lab (@{$XMLCourse->{"module"}}) {
   147 		push @Labs, $lab->{"code"};
   148 	}
   149 }
   151 sub load_class
   152 {
   153 	my $classfile =
   154 	$Config{"path_classes"}."/".$Config{"class"}.$Config{"class_suffix"};
   155 	$XMLClass = XMLin($classfile , ForceArray => [ 'student' ] )  
   156 		or die "Can't open file of the class ",$classfile,"\n";
   158 	for my $student (@{$XMLClass->{"student"}}) {
   159 		$Machines{$student->{"host"}} = {
   160 			"name"	=> "$student->{firstname} $student->{surname}",
   161 			"user"	=> "$student->{user}",
   162 			"student" => $student,
   163 		}	
   164 	}
   165 #	print Dumper($XMLClass);
   166 #	print Dumper(\%Machines);
   167 }
   170 sub lm_next
   171 {
   172 	for(my $i=0; $i<=$#Labs; $i++){
   173 		if ( $Labs[$i] eq $Run{"lab"} ) {
   174 			if ($i < $#Labs) {
   175 				lm_set($Labs[$i+1]);
   176 				return ;
   177 			} else {
   178 				die "Lab ", $Run{"lab"}, " is the last. Switch to next lab is impossible"
   179 			}
   180 		}
   182 	}
   183 	die "Lab ", $Run{"lab"}, " not found. Don't know which is next"
   184 }
   186 sub lm_prev
   187 # Switch to previous lab
   188 {
   189 	for(my $i=0; $i<=$#Labs; $i++){
   190 		if ( $Labs[$i] eq $Run{"lab"} ) {
   191 			if ($i > 0) {
   192 				lm_set($Labs[$i-1]);
   193 				return ;
   194 			} else {
   195 				die "Lab ", $Run{"lab"}, " is the first. Switch to previous lab is impossible"
   196 			}
   197 		}
   199 	}
   200 	die "Lab ", $Run{"lab"}, " not found. Don't know which is previous"
   201 }
   203 sub lm_set
   204 # Switch to $_[0] lab
   205 # FIXME
   206 {
   207 	my $lab = shift;
   208 	print "Current lab is $lab\n";
   209 	$Run{"lab"} = "$lab";
   210 	lm_do "setlab", $lab;
   211 }
   214 sub lm_start
   215 # Start new training day
   216 {
   217 	print_log(`date`." STARTED\n");
   218 	if ($Run{"lab"}) {
   219 		lm_next;
   220 	}
   221 	else
   222 	{
   223 		# First lab in the course
   224 		lm_set($Labs[0]);
   225 	}
   226 }
   228 sub lm_stop
   229 # Stop this training day
   230 {
   231 	print_log(`date`." STOPPED\n");
   232 }
   235 sub lm_show_hosts
   236 # Show hosts used to run a commands
   237 {
   238 	my $i=1;
   239 	for my $m (sort keys %Machines) {
   240 		if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) {
   241 			print "($i)","\t",$m,"\t",$Machines{$m}->{"name"},"\n";
   242 		}	
   243 		$i++;
   244 	}
   245 }
   247 sub lm_show_labs
   248 # Show hosts used to run a commands
   249 {
   250 	my $i=1;
   251 	for my $lab (@Labs) {
   252 		print $lab;
   253 		print "*" if $lab eq $Run{"lab"};
   254 		print "\n";
   255 	}
   256 }
   258 sub lm_do
   259 # Do the $_[0] command on all of the hosts 
   260 {
   261 	my $command = shift;
   262 	my $arg = join " ", @_;
   263 	my $i=1;
   264 	for my $m (sort keys %Machines) {
   265 		if (!@SelectedMachines || grep $_ eq $i, @SelectedMachines) {
   266 			print "$m:\n" if $Config{"show_host"} =~ /y/i;
   268 			my %myenv = ( %Config, 
   269 				host 	=>	$m,
   270 				dirs	=>	"/root /home/".$Machines{$m}->{"user"},
   271 				lablogs =>	$Config{"path_lablogs"}."/".
   272 						$XMLClass->{"course"}."/".
   273 						$XMLClass->{"date"}."/".
   274 						"$m",
   275 				lab	=> 	$arg,			
   277 				email	=>	$Machines{$m}->{"student"}->{"email"},
   278 				company	=>	$Machines{$m}->{"student"}->{"company"},
   279 				center 	=>	$XMLClass->{"center"},
   280 				course 	=>	$XMLClass->{"course"},
   281 				date 	=>	$XMLClass->{"date"},
   282 				name	=> 	$Machines{$m}->{"name"},
   283 				coursepath =>	$XMLCourse->{"path"},
   285 			);
   286 			if (grep { $_ eq $command} keys %Scripts) {
   287 				$_=$Scripts{"$command"};
   288 				s/\$(\w+)/$myenv{$1}/ge;
   289 				open(SHELL, "|/bin/sh -s");
   290 				binmode SHELL, ":utf8";
   291 				print SHELL $_;
   292 				close (SHELL);
   293 			}
   294 			else {
   295 				my $res = `ssh $Config{"ssh_user"}\@$m $command`;
   296 				if ($res) {
   297 					my $count = ($res =~ s/(^)/$m: /mg);
   298 					print $res;
   299 					print "\n" if ($count > 1);
   300 				}
   301 			}	
   302 		}	
   303 		$i++;
   304 	}
   305 }
   309 =cut comment
   311 lm report
   313 Построить html представление для журналов текущего класса.
   314 Для построения используется скрипт l3-report.
   316 =cut
   318 sub lm_report
   319 {
   321 	my $webdir = $Config{"path_web"};
   322 	my $course=$XMLClass->{"course"};
   323 	my $date=$XMLClass->{"date"};
   324 	my $encoding=$XMLClass->{"charset"};
   326 	print "date=$date\n";
   328 	for my $student (@{$XMLClass->{"student"}}) {
   329 		my $user = $student->{"user"};
   330 		my $hostname = $student->{"host"};
   331 		my $encoding = $student->{"encoding"};
   333 		system("mkdir -p $webdir/$date/$hostname");
   334 		system("cp ".$Config{"path_share"}."/*.{ico,css} $webdir/$date/$hostname");
   335 		system($Config{"l3-report"}.
   336 			" --input ".$Config{"path_lablogs"}."/$course/$date/$hostname/$user".
   337 			" --diffs ".$Config{"path_lablogs"}."/$course/$date/$hostname/$user ".
   338 				   $Config{"path_lablogs"}."/$course/$date/$hostname/root".
   339 			" --output $webdir/$date/$hostname/$user.html".
   340 			" --encoding $encoding"
   341 		);
   342 		system($Config{"l3-report"}.
   343 			" --input ".$Config{"path_lablogs"}."/$course/$date/$hostname/root".
   344 			" --diffs ".$Config{"path_lablogs"}."/$course/$date/$hostname/root ".
   345 			" --output $webdir/$date/$hostname/root.html".
   346 			" --encoding $encoding"
   347 		);
   348 	}
   349 }
   351 sub load_run
   352 {
   353 	my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"};
   354 	open (RUN, $runfile)
   355 		or return;
   356 	while (<RUN>) {
   357 		chomp;
   358 		my ($var, $val) = split /\s+/,$_,2;
   359 		$Run{$var}=$val;
   360 	}
   361 	close (RUN);	
   362 }
   364 sub save_run
   365 {
   366 	my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"};
   367 	open (RN, "$runfile")
   368 		or die "Can't save running state to $runfile";
   369 	for my $var (keys %Run) {
   370 		print RN $var,"\t",$Run{$var},"\n";
   371 	}
   372 	close (RN);	
   373 }
   375 sub print_log
   376 {
   377 	my $logfile = $Config{"path_labmaker"}."/".$Config{"path_logfile"};
   378 	open (LOG, ">>$logfile")
   379 		or die "Can't open logfile $logfile for writing";
   380 	print LOG  @_;
   381 	close (LOG);	
   382 }
   385 sub print_usage_info
   386 {
   387 	print "Usage:\n\n\t$0 [host-list] command\n";
   388 	while (<USAGE>) {
   389 		print $_;
   390 	}
   391 }
   393 __USAGE__
   395 Commands:
   397 	next		-- next lab
   398 	prev		-- prev lab
   399 	set LAB		-- set current lab to LAB
   400 	start		-- start this day training
   401 	stop		-- stop this day training
   402 	show hosts	-- show available hosts in the class
   403 	show labs	-- show available labs in the course
   404 	do COMMAND	-- do specified command on the hosts of hostlist
   405 	report		-- generate XML/HTML reports
   408 do commands:
   410 	install [PROFILE] -- install profile 
   412 Host list:	
   414 	@N		-- machine N
   415 	@N1-N2		-- all of the machines from N1 to N2
   416 	@N1,N2,N3	-- machine N1, N2 and N3
   418 	N* is numbers or domain names of the machines.
   420 	If host list is not specified, 
   421 	command is executed on all of the machines
   425 __SCRIPTS__
   426 ###install
   427 cat $sshkey | $lmssh $ssh_user@$host /bin/sh -c '"mkdir -p ~/.ssh; cat >>~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys"'
   429 ###install-lm
   430 cat $lminstall | ssh $ssh_user@$host /bin/sh -s $dirs
   432 ###copy-lablogs
   433 for i in $dirs
   434 do
   435 	mkdir -p $lablogs/${i##*/}
   436 	scp -q $ssh_user@$host:${i}/.labmaker/* $lablogs/${i##*/}
   437 done
   439 ###setlab
   440 for i in $dirs
   441 do
   442 	echo $lab | ssh $ssh_user@$host "cat > "${i}"/.labmaker/lab"
   443 done
   445 ###makeout
   446 common=$course-$date
   447 personal=$course-$date-$email
   448 mkdir -p $outpath/${common}/{Lablogs,Docs}
   449 mkdir -p $outpath/${personal}/{Course,Files}
   450 cd $outpath/${personal}
   451 ln -s ../${common}/Lablogs .
   452 ln -s ../${common}/Docs .
   453 cd ~-
   454 export UG_PERSONAL=${PWD}/$outpath/${personal}/Course
   455 export UG_CENTER="$center"
   456 export UG_COURSE="$course"
   457 export UG_DATE="$date"
   458 export UG_STUDENT="$name"
   459 export UG_COMPANY="$company"
   460 cd $coursepath; make personal; cd ~-
   462 ###watch
   463 cat taillast.pl | ssh $ssh_user@$host perl - /root/.labmaker
