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