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