You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2010/08/20 22:06:13 UTC

svn commit: r987623 [2/2] - in /incubator/vcl/trunk/managementnode/lib/VCL: Module/OS/Windows.pm Module/Provisioning/VMware/VMware.pm Module/Provisioning/VMware/vSphere_SDK.pm image.pm utils.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/image.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/image.pm?rev=987623&r1=987622&r2=987623&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/image.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/image.pm Fri Aug 20 20:06:13 2010
@@ -65,6 +65,7 @@ use 5.008000;
 use strict;
 use warnings;
 use diagnostics;
+use English '-no_match_vars';
 
 use VCL::utils;
 
@@ -106,8 +107,9 @@ sub process {
 	my $managementnode_shortname   = $self->data->get_management_node_short_name();
 	my $sysadmin_mail_address      = $self->data->get_management_node_sysadmin_email();
 
-	# Notify administrators that image creation is starting
-	my $body = <<"END";
+	if ($sysadmin_mail_address) {
+		# Notify administrators that image creation is starting
+		my $body = <<"END";
 VCL Image Creation Started
 
 Request ID: $request_id
@@ -129,8 +131,9 @@ Computer name: $computer_shortname
 
 Use Sysprep: $imagemeta_sysprep
 END
-	mail($sysadmin_mail_address, "VCL IMAGE Creation Started: $image_name", $body, $affiliation_helpaddress);
-
+		mail($sysadmin_mail_address, "VCL IMAGE Creation Started: $image_name", $body, $affiliation_helpaddress);
+	}
+	
 	# Make sure image does not exist in the repository
 	my $image_already_exists = $self->provisioner->does_image_exist();
 	if ($image_already_exists) {
@@ -460,6 +463,321 @@ END
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 setup
+
+ Parameters  : none
+ Returns     : 
+ Description : This subroutine is used when vcld is run in setup mode. It
+               presents a menu for the image module.
+
+=cut
+
+sub setup {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	push @{$ENV{setup_path}}, 'Image';
+	
+	my @operation_choices = (
+		'Capture Base Image',
+	);
+	
+	my @setup_path = @{$ENV{setup_path}};
+	OPERATION: while (1) {
+		@{$ENV{setup_path}} = @setup_path;
+		
+		print '-' x 76 . "\n";
+		
+		print "Choose an operation:\n";
+		my $operation_choice_index = setup_get_array_choice(@operation_choices);
+		last if (!defined($operation_choice_index));
+		my $operation_name = $operation_choices[$operation_choice_index];
+		print "\n";
+		
+		push @{$ENV{setup_path}}, $operation_name;
+		
+		if ($operation_name =~ /capture/i) {
+			$self->setup_capture_base_image();
+		}
+	}
+	
+	pop @{$ENV{setup_path}};
+	return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 setup_capture_base_image
+
+ Parameters  : none
+ Returns     : 
+ Description : This subroutine is used when vcld is run in setup mode. It
+               inserts the database entries necessary to capture a base image.
+               Several questions are presented to the user via the command line.
+
+=cut
+
+sub setup_capture_base_image {
+	my $self = shift;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	# Get the management node id, needed to insert a reservation row later on
+	my $management_node_id = $self->data->get_management_node_id();
+	if (!$management_node_id) {
+		print "ERROR: failed to determine the management node ID\n";
+		return;
+	}
+	
+	# Get the user who the reservation and image will belong to
+	my $user_id;
+	my $username;
+	while (!$user_id) {
+		my $user_identifier = setup_get_input_string("Enter the VCL login name or ID of the user who will own the image:", 'admin');
+		return if (!defined($user_identifier));
+		my $user_info = get_user_info($user_identifier);
+		if (!$user_info) {
+			print "User was not found: $user_identifier\n";
+		}
+		else {
+			$user_id = (keys %$user_info)[0];
+			$username = $user_info->{$user_id}{unityid};
+		}
+	}
+	print "\nUser who will own the image: $username (ID: $user_id)\n\n";
+	
+	# Determine the computer ID
+	my $computer_id;
+	my %computer_info;
+	while (!$computer_id) {
+		my $computer_identifier = setup_get_input_string("Enter the hostname or IP address of the computer to be captured:");
+		return if (!defined($computer_identifier));
+		
+		# Search the computer table for a match
+		my @computer_ids = get_computer_ids($computer_identifier);
+		if (!@computer_ids) {
+			print "No VCL computers were found with the name or IP address: $computer_identifier\n";
+			next;
+		}
+		
+		# Get information from the database for all of the computers found
+		for my $computer_id (@computer_ids) {
+			$computer_info{$computer_id} = get_computer_info($computer_id)->{computer};
+			if (!$computer_info{$computer_id}) {
+				print "ERROR: unable to retrieve information for computer ID: $computer_id\n";
+				return;
+			}
+		}
+	
+		if (scalar(@computer_ids) > 1) {
+			print "Multiple VCL computers were found with the name or IP address: '$computer_identifier' (@computer_ids)\n\n";
+			print "Choose a computer:\n";
+			$computer_id = setup_get_hash_choice(\%computer_info, 'hostname');
+			return if (!defined($computer_id));
+		}
+		else {
+			$computer_id = (keys %computer_info)[0];
+		}
+	}
+	
+	my $computer_hostname = $computer_info{$computer_id}{hostname};
+	my $computer_state_name = $computer_info{$computer_id}{state}{name};
+	my $computer_provisioning_module_name = $computer_info{$computer_id}{provisioning}{module}{name};
+	
+	my $install_type;
+	if ($computer_provisioning_module_name =~ /vm/i) {
+		$install_type = 'vmware';
+	}
+	else {
+		$install_type = 'partimage';
+	}
+	
+	print "\nComputer to be captured: $computer_hostname (ID: $computer_id)\n";
+	print "Provisioning module: $computer_provisioning_module_name\n";
+	print "Install type: $install_type\n";
+	print "\n";
+	
+	# Make sure the computer state is valid
+	if ($computer_state_name =~ /(maintenance|deleted)/i) {
+		print "ERROR: state of $computer_hostname is $computer_state_name\n";
+		return;
+	}
+	
+	
+	# Get the OS table contents from the database
+	my $os_info = get_os_info();
+	if (!$os_info) {
+		print "ERROR: failed to retrieve OS info from the database\n";
+		return;
+	}
+
+	# Loop through the OS table info
+	for my $os_id (keys %$os_info) {
+		# Remove keys which don't match the selected computer type
+		# Remove keys where the name begins with esx - deprecated OS type
+		if ($os_info->{$os_id}{installtype} ne $install_type || $os_info->{$os_id}{name} =~ /^vmwareesx/i) {
+			delete $os_info->{$os_id};
+		}
+	}
+
+	print "Select the OS to be captured (install type: $install_type):\n";
+	my $os_id = setup_get_hash_choice($os_info, 'prettyname');
+	return if (!defined($os_id));
+	my $os_prettyname = $os_info->{$os_id}{prettyname};
+	my $os_module_perl_package = $os_info->{$os_id}{module}{perlpackage};
+	my $os_type = $os_info->{$os_id}{type};
+	print "\nSelected OS: $os_prettyname\n\n";
+	
+	# If Windows, ask if Sysprep should be used
+	my $use_sysprep = 1;
+	if ($os_type =~ /windows/i) {
+		my @yes_no_choices = (
+			'Yes',
+			'No',
+		);
+		
+		print "Use Sysprep:\n";
+		my $sysprep_choice_index = setup_get_array_choice(@yes_no_choices);
+		last if (!defined($sysprep_choice_index));
+		my $use_sysprep_choice = $yes_no_choices[$sysprep_choice_index];
+		print "\nUse Sysprep: $use_sysprep_choice\n\n";
+		
+		if ($use_sysprep_choice =~ /no/i) {
+			$use_sysprep = 0;
+		}
+	}
+	
+	my $image_prettyname;
+	while (!$image_prettyname) {
+		$image_prettyname = setup_get_input_string("Enter the name of the image to be captured:");
+		return if (!defined($image_prettyname));
+		#if ($image_prettyname =~ //) {
+		#	print "Image name is not valid: $image_prettyname\n";
+		#	$image_prettyname = 0;
+		#}
+	}
+	
+	my $image_name = $image_prettyname;
+	$image_name =~ s/[\s\W]//g;
+	$image_name = $os_info->{$os_id}{name} . "-$image_name-v0";
+	
+	my $insert_imagemeta_statement = <<EOF;
+INSERT INTO imagemeta
+(sysprep)
+VALUES
+('$use_sysprep')
+EOF
+	
+	my $imagemeta_id = database_execute($insert_imagemeta_statement);
+	if (!defined($imagemeta_id)) {
+		print "ERROR: failed to insert into imagemeta table\n";
+		return;
+	}
+	
+	
+	my $insert_image_statement = <<EOF;
+INSERT INTO image (name, prettyname, ownerid, platformid, OSid, imagemetaid, deleted, lastupdate, size, architecture, basedoffrevisionid)
+VALUES ('$image_name', '$image_prettyname', '$user_id', '1', $os_id, $imagemeta_id, '1', NOW( ), '1450', 'x86', '4')
+EOF
+	
+	my $image_id = database_execute($insert_image_statement);
+	if (!defined($image_id)) {
+		print "ERROR: failed to insert into image table\n";
+		return;
+	}
+	
+	# Add the newly inserted image ID to the image name
+	$image_name =~ s/-v0$/$image_id-v0/;
+	
+	# Upadate the name in the image table
+	my $update_image_statement = <<EOF;
+UPDATE image
+SET name = '$image_name'
+WHERE
+id = $image_id
+EOF
+	if (!database_execute($update_image_statement)) {
+		print "ERROR: failed to update the image table with the correct image name: $image_name\n";
+		return;
+	}
+	
+	
+	my $insert_imagerevision_statement = <<EOF;
+INSERT INTO imagerevision
+(imageid, revision, userid, datecreated, deleted, production, imagename)
+VALUES
+($image_id, '0', '$user_id', NOW( ), '1', '1', '$image_name')
+EOF
+
+	my $imagerevision_id = database_execute($insert_imagerevision_statement);
+	if (!defined($imagerevision_id)) {
+		print "ERROR: failed to insert into imagerevision table\n";
+		return;
+	}
+
+	my $insert_resource_statement = <<EOF;
+INSERT INTO resource
+(resourcetypeid, subid)
+VALUES ('13', '$image_id')
+EOF
+
+	my $resource_id = database_execute($insert_resource_statement);
+	if (!defined($resource_id)) {
+		print "ERROR: failed to insert into resource table\n";
+		return;
+	}
+	
+	print "\nAdded new image to database: '$image_prettyname'\n";
+	print "   image.name: $image_name\n";
+	print "   image.id: $image_id\n";
+	print "   imagerevision.id: $imagerevision_id\n";
+	print "   imagemeta.id: $imagemeta_id\n";
+	print "   resource.id: $resource_id\n\n";
+	
+	
+	my ($request_id, $reservation_id) = insert_request($management_node_id, 'image', 'image', 0, $username, $computer_id, $image_id, $imagerevision_id, 0, 60);
+	if (!defined($request_id) || !defined($reservation_id)) {
+		print "ERROR: failed to insert new imaging request\n";
+		return;
+	}
+	
+	my $message = <<EOF;
+Inserted imaging request to the database:
+request ID: $request_id
+reservation ID: $reservation_id
+
+This process will now display the contents of the vcld.log file if the vcld
+daemon is running. If you do not see many lines of additional output, exit this
+process, start the vcld daemon, and monitor the image capture process by running
+the command:
+tail -f $LOGFILE | grep '$request_id:$reservation_id'
+
+EOF
+	
+	print '-' x 76 . "\n";
+	print "$message";
+	print '-' x 76 . "\n";
+	
+	# Pipe the command output to a file handle
+	# The open function returns the pid of the process
+	if (open(COMMAND, "tail -f $LOGFILE 2>&1 |")) {
+		# Capture the output of the command
+		
+		while (my $output = <COMMAND>) {
+			print $output if ($output =~ /$reservation_id/);
+		}
+	}
+	
+	exit;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 1;
 __END__
 

Modified: incubator/vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=987623&r1=987622&r2=987623&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/utils.pm Fri Aug 20 20:06:13 2010
@@ -108,8 +108,10 @@ our @EXPORT = qw(
   format_number
   get_affiliation_info
   get_block_request_image_info
+  get_caller_trace
   get_computer_current_state_name
   get_computer_grp_members
+  get_computer_ids
   get_computer_info
   get_computers_controlled_by_MN
   get_current_file_name
@@ -127,12 +129,14 @@ our @EXPORT = qw(
   get_management_predictive_info
   get_module_info
   get_next_image_default
+  get_os_info
   get_production_imagerevision_info
   get_request_by_computerid
   get_request_end
   get_request_info
   get_resource_groups
   get_managable_resource_groups
+  get_user_info
   get_vmhost_info
   get_user_info
   getdynamicaddress
@@ -8243,6 +8247,50 @@ EOF
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_computer_ids
+
+ Parameters  : $computer_identifier
+ Returns     : array
+ Description : Queries the computer table for computers matching the
+               $computer_identifier argument. The argument may contain either
+               the computer's hostname or IP address. An array containing the
+               computer IDs is returned.
+
+=cut
+
+sub get_computer_ids {
+	my ($computer_identifier) = @_;
+
+	if(!defined($computer_identifier)){
+		notify($ERRORS{'WARNING'}, $LOGFILE, "computer identifier argument was not supplied");
+		return;
+	}
+
+	my $select_statement = <<EOF;
+SELECT
+*
+FROM
+computer
+WHERE
+hostname LIKE '$computer_identifier'
+OR hostname LIKE '$computer_identifier.%'
+OR IPaddress = '$computer_identifier'
+OR privateIPaddress = '$computer_identifier'
+EOF
+
+	my @selected_rows = database_select($select_statement);
+	if (!@selected_rows) {
+		notify($ERRORS{'DEBUG'}, 0, "no computers were found matching identifier: $computer_identifier");
+		return ();
+	}
+
+	my @computer_ids = map { $_->{id} } @selected_rows;
+	notify($ERRORS{'DEBUG'}, 0, "found computers matching identifier: $computer_identifier, IDs: @computer_ids");
+	return sort @computer_ids;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 insert_request
 
  Parameters  : $managementnode_id, $request_state_name, $request_laststate_name, $end_minutes_in_future, $user_unityid, $computer_id, $image_id, $imagerevision_id
@@ -9549,6 +9597,64 @@ sub get_module_info {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_user_info
+
+ Parameters  : $user_identifier
+ Returns     : hash reference
+ Description : Retrieves information from the database for the user specified by
+               the $user_identifier argument. The $user_identifier argument can
+               either be a user ID or login name.
+
+=cut
+
+sub get_user_info {
+	my ($user_identifier) = @_;
+	if (!defined($user_identifier)) {
+		notify($ERRORS{'WARNING'}, 0, "user identifier argument was not specified");
+		return;
+	}
+	
+	my $select_statement = <<EOF;
+SELECT
+*
+FROM
+user
+WHERE
+EOF
+	
+	if ($user_identifier =~ /^\d+$/) {
+		$select_statement .= "id = $user_identifier";
+	}
+	else {
+		$select_statement .= "unityid = '$user_identifier'";
+	}
+	
+	# Call the database select subroutine
+	my @selected_rows = database_select($select_statement);
+
+	# Check to make sure rows were returned
+	if (!@selected_rows) {
+		notify($ERRORS{'WARNING'}, 0, "unable to retrieve rows from user table");
+		return;
+	}
+	
+	# Transform the array of database rows into a hash
+	my %info_hash;
+	for my $row (@selected_rows) {
+		my $user_id = $row->{id};
+		
+		for my $key (keys %$row) {
+			my $value = $row->{$key};
+			$info_hash{$user_id}{$key} = $value;
+		}
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "retrieved user info:\n" . format_data(\%info_hash));
+	return \%info_hash;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_current_package_name
 
  Parameters  : None
@@ -10080,6 +10186,58 @@ sub setup_print_wrap {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_os_info
+
+ Parameters  : none
+ Returns     : hash reference
+ Description : Returns the contents of the OS table as a hash reference. The
+               hash keys are the OS IDs.
+
+=cut
+
+sub get_os_info {
+	# Create the select statement
+	my $select_statement = <<EOF;
+SELECT
+OS.*,
+module.name AS module_name,
+module.prettyname AS module_prettyname,
+module.perlpackage AS module_perlpackage
+FROM
+OS,
+module
+WHERE
+OS.moduleid = module.id
+EOF
+	
+	# Call the database select subroutine
+	my @selected_rows = database_select($select_statement);
+	
+	my %info;
+	
+	for my $row (@selected_rows) {
+		my $os_id = $row->{id};
+		
+		foreach my $key (keys %$row) {
+			my $value = $row->{$key};
+			
+			(my $original_key = $key) =~ s/^.+_//;
+	
+			if ($key =~ /module_/) {
+				 $info{$os_id}{module}{$original_key} = $value;
+			}
+			else {
+				$info{$os_id}{$original_key} = $value;
+			}
+		}
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "retrieved OS info:\n" . format_data(\%info));
+	return \%info;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 1;
 __END__