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