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 2009/07/15 16:30:16 UTC

svn commit: r794283 - in /incubator/vcl/trunk/managementnode/lib/VCL: DataStructure.pm Module/Provisioning/vmware.pm Module/Provisioning/xCAT.pm utils.pm

Author: arkurth
Date: Wed Jul 15 14:30:16 2009
New Revision: 794283

URL: http://svn.apache.org/viewvc?rev=794283&view=rev
Log:
VCL-167
There was a bug in the regex which was attempting to find "Offending key" and "Matching host key" lines in SSH output. Removed ^ from beginning of regex. It now finds the lines.

VCL-183
Removed DataStructure.pm::get_computer_private_ip() sub and created a sub with the same name which only calls get_computer_private_ip_address(). This is so subs with both names exist while the rest of the code which calls either sub is transitioned to only call get_computer_private_ip_address().

Removed utils.pm::get_ip_address_from_hosts(). It was only being called by DataStructure.pm::get_computer_private_ip().

Also fixed bug in regex in get_computer_private_ip_address(). It wasn't handling computer names correctly if names had the same prefix, ie blade1g4-1 and blade1g4-14.

VCL-81
Added is_management_node_process_running() sub to utils.pm. This runs pgrep to determine if a process is running on the management node. It is used to determine if another SCP process is already running to retrieve a given image from another management node.

Updated does_image_exist() subs in vmware.pm and xCAT.pm. The subs now check if an SCP process is running to retrieve the image before checking if the image files exist. If running, they wait and keep checking. This will prevent does_image_exist() from returning true if a partial image exists which is actively being copied.

Updated retrieve_image() subs in vmware.pm and xCAT.pm. The subs now check all partner management nodes and try to retrieve from the partner with the largest image. This will prevent retrieval from a partner which contains a partial image, which could happen if that partner is actively retrieving the same image from another partner.


Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/vmware.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm
    incubator/vcl/trunk/managementnode/lib/VCL/utils.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=794283&r1=794282&r2=794283&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Wed Jul 15 14:30:16 2009
@@ -912,36 +912,6 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 get_computer_private_ip
-
- Parameters  : None
- Returns     : IP address string if successful, 0 if failed
- Description :
-
-=cut
-
-sub get_computer_private_ip {
-	my $self = shift;
-
-	# Get the computer short name from this DataStructure
-	my $computer_short_name = $self->get_computer_short_name();
-	if (!$computer_short_name) {
-		notify($ERRORS{'WARNING'}, 0, "computer short name could not be retrieved");
-		return 0;
-	}
-
-	# Get the node's private IP address from the hosts file
-	if (my $computer_private_ip = get_ip_address_from_hosts($computer_short_name)) {
-		return $computer_private_ip;
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "unable to locate private IP address for $computer_short_name in hosts file");
-		return 0;
-	}
-} ## end sub get_computer_private_ip
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 get_reservation_remote_ip
 
  Parameters  : None
@@ -1427,6 +1397,10 @@
 
 =cut
 
+sub get_computer_private_ip {
+	return get_computer_private_ip_address(@_);
+}
+
 sub get_computer_private_ip_address {
 	my $self;
 	my $argument = shift;
@@ -1486,7 +1460,7 @@
 	}
 	
 	# Find lines containing the computer name
-	my @matching_computer_hosts_lines = grep(/\s$computer_name/i, @$output);
+	my @matching_computer_hosts_lines = grep(/\s$computer_name\s*$/i, @$output);
 	
 	# Extract matching lines which aren't commented out
 	my @uncommented_computer_hosts_lines = grep(/^\s*[^#]/, @matching_computer_hosts_lines);

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/vmware.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/vmware.pm?rev=794283&r1=794282&r2=794283&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/vmware.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/vmware.pm Wed Jul 15 14:30:16 2009
@@ -2255,42 +2255,81 @@
 
 sub does_image_exist {
 	my $self = shift;
-	if (ref($self) !~ /vmware/i) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return 0;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
+		return;	
 	}
 
-	my $image_name = $self->data->get_image_name();
+	# Get the image name, first try passed argument, then data
+	my $image_name = shift;
+	$image_name = $self->data->get_image_name() if !$image_name;
 	if (!$image_name) {
-		notify($ERRORS{'CRITICAL'}, 0, "unable to determine if image exists, unable to determine image name");
-		return 0;
+		notify($ERRORS{'WARNING'}, 0, "unable to determine image name");
+		return;
 	}
 
-	my $IMAGEREPOSITORY;
-
-	if ($image_name =~ /^(vmware)/) {
-		$IMAGEREPOSITORY = "$VMWAREREPOSITORY";
+	# Get the image repository path
+	my $image_repository_path = $self->_get_image_repository_path();
+	if (!$image_repository_path) {
+		notify($ERRORS{'WARNING'}, 0, "image repository path could not be determined");
+		return;
 	}
 	else {
-		notify($ERRORS{'CRITICAL'}, 0, "unable to determine if image exists, image name is not vmware image_name= $image_name");
-		return 0;
+		notify($ERRORS{'DEBUG'}, 0, "image repository path: $image_repository_path");
 	}
-
-	if (open(IMAGES, "/bin/ls -1 $IMAGEREPOSITORY 2>&1 |")) {
-		my @images = <IMAGES>;
-		close(IMAGES);
-		foreach my $i (@images) {
-			if ($i =~ /$image_name/) {
-				notify($ERRORS{'OK'}, 0, "image $image_name exists");
-				return 1;
-			}
+	
+	# Make sure an scp process isn't currently running to retrieve the image
+	# This can happen if another reservation is running for the same image and the management node didn't have a copy
+	my $scp_wait_attempt = 0;
+	my $scp_wait_max_attempts = 40;
+	my $scp_wait_delay = 15;
+	while (is_management_node_process_running("scp.*$image_name")) {
+		$scp_wait_attempt++;
+		
+		notify($ERRORS{'OK'}, 0, "attempt $scp_wait_attempt/$scp_wait_max_attempts: scp process is running to retrieve $image_name, waiting for $scp_wait_delay seconds");
+		
+		if ($scp_wait_attempt == $scp_wait_max_attempts) {
+			notify($ERRORS{'WARNING'}, 0, "attempt $scp_wait_attempt/$scp_wait_max_attempts: waited maximum amount of time for scp process to terminate to retrieve $image_name");
+			return;
 		}
-	} ## end if (open(IMAGES, "/bin/ls -1 $IMAGEREPOSITORY 2>&1 |"...
-
-	notify($ERRORS{'OK'}, 0, "image $IMAGEREPOSITORY/$image_name does NOT exist");
-	return 0;
+		
+		sleep $scp_wait_delay;
+	}
+	notify($ERRORS{'DEBUG'}, 0, "scp process is not running to retrieve $image_name");
+	
+	# Run du to get the size of the image files if the image exists
+	my $du_command = "du -c $image_repository_path/*$image_name* 2>&1 | grep total 2>&1";
+	my ($du_exit_status, $du_output) = run_command($du_command);
+	
+	# If the partner doesn't have the image, a "no such file" error should be displayed
+	my $image_files_exist;
+	if (defined(@$du_output) && grep(/no such file/i, @$du_output)) {
+		notify($ERRORS{'OK'}, 0, "$image_name does NOT exist");
+		$image_files_exist = 0;
+	}
+	elsif (defined(@$du_output) && !grep(/\d+\s+total/i, @$du_output)) {
+		notify($ERRORS{'WARNING'}, 0, "du output does not contain a total line:\n" . join("\n", @$du_output));
+		return;
+	}
+	elsif (!defined($du_exit_status)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if image $image_name exists");
+		return;
+	}
+	
+	# Return 1 if the image size > 0
+	my ($image_size) = (@$du_output[0] =~ /(\d+)\s+total/);
+	if ($image_size && $image_size > 0) {
+		my $image_size_mb = int($image_size / 1024);
+		notify($ERRORS{'DEBUG'}, 0, "$image_name exists in $image_repository_path, size: $image_size_mb MB");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "image does NOT exist: $image_name");
+		return 0;
+	}
 
 } ## end sub does_image_exist
+	
 #/////////////////////////////////////////////////////////////////////////////
 
 =head2 retrieve_image
@@ -2303,119 +2342,135 @@
 
 sub retrieve_image {
 	my $self = shift;
-	if (ref($self) !~ /vmware/i) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
+		return;	
 	}
 
-	# Make sure imag library functions are enabled
+	# Make sure image library functions are enabled
 	my $image_lib_enable = $self->data->get_management_node_image_lib_enable();
 	if (!$image_lib_enable) {
 		notify($ERRORS{'OK'}, 0, "image library functions are disabled");
 		return;
 	}
 
-	# Get the image name
-	my $image_name = shift;
-	$image_name = $self->data->get_image_name() if !$image_name;
+	# If an argument was specified, use it as the image name
+	# If not, get the image name from the reservation data
+	my $image_name = shift || $self->data->get_image_name();
 	if (!$image_name) {
-		notify($ERRORS{'WARNING'}, 0, "unable to determine image name");
+		notify($ERRORS{'WARNING'}, 0, "unable to determine image name from argument or reservation data");
 		return;
 	}
-
-	# Get the other image library variables
-	my $image_lib_user     = $self->data->get_management_node_image_lib_user()     || 'undefined';
-	my $image_lib_key      = $self->data->get_management_node_image_lib_key()      || 'undefined';
-	my $image_lib_partners = $self->data->get_management_node_image_lib_partners() || 'undefined';
-	if ("$image_lib_user $image_lib_key $image_lib_partners" =~ /undefined/) {
-		notify($ERRORS{'WARNING'}, 0, "image library configuration data is missing: user=$image_lib_user, key=$image_lib_key, partners=$image_lib_partners");
-		return;
+	
+	# Make sure image does not already exist on this management node
+	if ($self->does_image_exist($image_name)) {
+		notify($ERRORS{'OK'}, 0, "$image_name already exists on this management node");
+		return 1;
 	}
 
-	# Get the image repository path
-	my $image_repository_path = $self->_get_image_repository_path();
-	if (!$image_repository_path) {
-		notify($ERRORS{'WARNING'}, 0, "image repository path could not be determined");
+	# Get the image library partner string
+	my $image_lib_partners = $self->data->get_management_node_image_lib_partners();
+	if (!$image_lib_partners) {
+		notify($ERRORS{'WARNING'}, 0, "image library partners could not be determined");
 		return;
 	}
-
-	# Attempt to copy image from other management nodes
-	notify($ERRORS{'OK'}, 0, "attempting to copy $image_name from other management nodes");
-
+	
 	# Split up the partner list
 	my @partner_list = split(/,/, $image_lib_partners);
 	if ((scalar @partner_list) == 0) {
 		notify($ERRORS{'WARNING'}, 0, "image lib partners variable is not listed correctly or does not contain any information: $image_lib_partners");
 		return;
 	}
-
-	# Loop through the partners, attempt to copy
+	
+	# Get the local image repository path
+	my $image_repository_path_local = $self->_get_image_repository_path();
+	if (!$image_repository_path_local) {
+		notify($ERRORS{'WARNING'}, 0, "image repository path could not be determined");
+		return;
+	}
+	
+	# Loop through the partners
+	# Find partners which have the image
+	# Check size for each partner
+	# Retrieve image from partner with largest image
+	# It's possible that another partner (management node) is currently copying the image from another managment node
+	# This should prevent copying a partial image
+	my $largest_partner;
+	my $largest_partner_hostname;
+	my $largest_partner_image_lib_user;
+	my $largest_partner_image_lib_key;
+	my $largest_partner_ssh_port;
+	my $largest_partner_path;
+	my $largest_partner_size = 0;
+	
+	notify($ERRORS{'OK'}, 0, "attempting to find another management node that contains $image_name");
 	foreach my $partner (@partner_list) {
-		notify($ERRORS{'OK'}, 0, "checking if $partner has $image_name");
-
-		# Use ssh to call ls on the partner management node
-		my ($ls_exit_status, $ls_output_array_ref) = run_ssh_command($partner, $image_lib_key, "ls -1 $image_repository_path", $image_lib_user);
-
-		# Check if the ssh command failed
-		if (!$ls_output_array_ref) {
-			notify($ERRORS{'WARNING'}, 0, "unable to run ls command via ssh on $partner");
+		# Get the connection information for the partner management node
+		my $partner_hostname = $self->data->get_management_node_hostname($partner) || '';
+		my $partner_image_lib_user = $self->data->get_management_node_image_lib_user($partner) || '';
+		my $partner_image_lib_key = $self->data->get_management_node_image_lib_key($partner) || '';
+		my $partner_ssh_port = $self->data->get_management_node_ssh_port($partner) || '';
+		my $image_repository_path_remote = $self->_get_image_repository_path($partner);
+		
+		notify($ERRORS{'OK'}, 0, "checking if $partner_hostname has image $image_name");
+		notify($ERRORS{'DEBUG'}, 0, "remote image repository path on $partner: $image_repository_path_remote");
+		
+		# Run du to get the size of the image files on the partner if the image exists
+		my ($du_exit_status, $du_output) = run_ssh_command($partner, $partner_image_lib_key, "du -c $image_repository_path_remote/*$image_name* | grep total", $partner_image_lib_user, $partner_ssh_port, 1);
+		
+		# If the partner doesn't have the image, a "no such file" error should be displayed
+		if (defined(@$du_output) && grep(/no such file/i, @$du_output)) {
+			notify($ERRORS{'OK'}, 0, "$image_name does NOT exist on $partner_hostname");
 			next;
 		}
-
-		# Convert the output array to a string
-		my $ls_output = join("\n", @{$ls_output_array_ref});
-
-		# Check the ls output for permission denied
-		if ($ls_output =~ /permission denied/i) {
-			notify($ERRORS{'CRITICAL'}, 0, "permission denied when checking if $partner has $image_name, exit status=$ls_exit_status, output:\n$ls_output");
+		elsif (defined(@$du_output) && !grep(/\d+\s+total/i, @$du_output)) {
+			notify($ERRORS{'WARNING'}, 0, "du output does not contain a total line:\n" . join("\n", @$du_output));
 			next;
 		}
-
-		# Check the ls output for the image name
-		if ($ls_output !~ /$image_name/i) {
-			notify($ERRORS{'OK'}, 0, "$image_name does not exist on $partner");
+		elsif (!defined($du_exit_status)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if image $image_name exists on $partner_hostname");
 			next;
 		}
-
-		# Image exists
-		notify($ERRORS{'OK'}, 0, "$image_name exists on $partner, attempting to copy");
-
-		#set lockfile - prevent process from loading while a copy is in progress
-
-		my $lock = "$image_repository_path/$image_name.copylock";
-		if (sysopen(SEM, $lock, O_RDONLY | O_CREAT)) {
-			if (flock(SEM, LOCK_EX)) {
-				notify($ERRORS{'OK'}, 0, "set Exclusive lock on $lock");
-				# Attempt copy
-				if (run_scp_command("$image_lib_user\@$partner:$image_repository_path/$image_name*", $image_repository_path, $image_lib_key)) {
-					notify($ERRORS{'OK'}, 0, "$image_name files copied via SCP");
-					close(SEM);
-					notify($ERRORS{'OK'}, 0, "releasing exclusive lock on $lock, proceeding");
-					unlink($lock);
-					last;
-				}
-				else {
-					notify($ERRORS{'WARNING'}, 0, "unable to copy $image_name files via SCP");
-					close(SEM);
-					notify($ERRORS{'OK'}, 0, "releasing exclusive lock on $lock, proceeding");
-					unlink($lock);
-					next;
-				}
-			} ## end if (flock(SEM, LOCK_EX))
-		} ## end if (sysopen(SEM, $lock, O_RDONLY | O_CREAT...
-
-
-	} ## end foreach my $partner (@partner_list)
-
-	# Make sure image was copied
-	if ($self->does_image_exist($image_name)) {
-		notify($ERRORS{'OK'}, 0, "$image_name was copied to this management node");
-		return 1;
+		
+		# Extract the image size in bytes from the du total output line
+		my ($partner_image_size) = (@$du_output[0] =~ /(\d+)\s+total/);
+		notify($ERRORS{'OK'}, 0, "$image_name exists on $partner_hostname, size: $partner_image_size bytes");
+		
+		# Check if the image size is larger than any previously found, if so, save the partner info
+		if ($partner_image_size > $largest_partner_size) {
+			$largest_partner = $partner;
+			$largest_partner_hostname = $partner_hostname;
+			$largest_partner_size = $partner_image_size;
+			$largest_partner_image_lib_user = $partner_image_lib_user;
+			$largest_partner_image_lib_key = $partner_image_lib_key;
+			$largest_partner_ssh_port = $partner_ssh_port;
+			$largest_partner_path = $image_repository_path_remote;
+		}
+	}
+	
+	# Check if any partner was found
+	if (!$largest_partner) {
+		notify($ERRORS{'WARNING'}, 0, "unable to find $image_name on other management nodes");
+		return;
+	}
+	
+	# Attempt copy
+	notify($ERRORS{'OK'}, 0, "attempting to retrieve $image_name from $largest_partner_hostname");
+	if (run_scp_command("$largest_partner_image_lib_user\@$largest_partner:$largest_partner_path/$image_name*", $image_repository_path_local, $largest_partner_image_lib_key, $largest_partner_ssh_port)) {
+		notify($ERRORS{'OK'}, 0, "image $image_name was copied from $largest_partner_hostname");
 	}
 	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to copy image $image_name from $largest_partner_hostname");
+		next;
+	}
+	
+	# Make sure image was copied
+	if (!$self->does_image_exist($image_name)) {
 		notify($ERRORS{'WARNING'}, 0, "$image_name was not copied to this management node");
 		return 0;
 	}
+
+	return 1;
 } ## end sub retrieve_image
 
 #/////////////////////////////////////////////////////////////////////////////

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm?rev=794283&r1=794282&r2=794283&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm Wed Jul 15 14:30:16 2009
@@ -2837,19 +2837,23 @@
  Parameters  : optional: image name
  Returns     : 1 if image exists, 0 if it doesn't
  Description : Checks the management node's local image repository for the
-               existence of the requested image. This subroutine does not
-					attempt to copy the image from another management node. The
-					retrieve_image() subroutine does this. Callers of
-					does_image_exist must also call retrieve_image if image library
-					retrieval functionality is desired.
+					existence of the requested image and xCAT template (.tmpl) file.
+					If the image files exist but the .tmpl file does not, it creates
+					the .tmpl file. If a .tmpl file exists but the image files do
+					not, it deletetes the orphaned .tmpl file.
+					
+					This subroutine does not attempt to copy the image from another
+					management node. The retrieve_image() subroutine does this.
+					Callers of does_image_exist must also call retrieve_image if
+					image library retrieval functionality is desired.
 
 =cut
 
 sub does_image_exist {
 	my $self = shift;
-	if (ref($self) !~ /xCAT/i) {
-		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
-		return 0;
+	unless (ref($self) && $self->isa('VCL::Module')) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method");
+		return;	
 	}
 
 	# Get the image name, first try passed argument, then data
@@ -2859,6 +2863,16 @@
 		notify($ERRORS{'WARNING'}, 0, "unable to determine image name");
 		return;
 	}
+	
+	# Get the image install type
+	my $image_os_install_type = $self->data->get_image_os_install_type();
+	if (!$image_os_install_type) {
+		notify($ERRORS{'WARNING'}, 0, "image OS install type could not be determined");
+		return;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "image OS install type: $image_os_install_type");
+	}
 
 	# Get the image repository path
 	my $image_repository_path = $self->_get_image_repository_path();
@@ -2869,17 +2883,74 @@
 	else {
 		notify($ERRORS{'DEBUG'}, 0, "image repository path: $image_repository_path");
 	}
+	
+	# Make sure an scp process isn't currently running to retrieve the image
+	# This can happen if another reservation is running for the same image and the management node didn't have a copy
+	my $scp_wait_attempt = 0;
+	my $scp_wait_max_attempts = 40;
+	my $scp_wait_delay = 15;
+	while (is_management_node_process_running("scp.*$image_name")) {
+		$scp_wait_attempt++;
+		
+		notify($ERRORS{'OK'}, 0, "attempt $scp_wait_attempt/$scp_wait_max_attempts: scp process is running to retrieve $image_name, waiting for $scp_wait_delay seconds");
+		
+		if ($scp_wait_attempt == $scp_wait_max_attempts) {
+			notify($ERRORS{'WARNING'}, 0, "attempt $scp_wait_attempt/$scp_wait_max_attempts: waited maximum amount of time for scp process to terminate to retrieve $image_name");
+			return;
+		}
+		
+		sleep $scp_wait_delay;
+	}
+	notify($ERRORS{'DEBUG'}, 0, "scp process is not running to retrieve $image_name");
+	
+	# Run du to get the size of the image files if the image exists
+	my $du_command;
+	if ($image_os_install_type eq 'kickstart') {
+		$du_command = "du -c $image_repository_path 2>&1 | grep total 2>&1"
+	}
+	else {
+		$du_command = "du -c $image_repository_path/*$image_name* 2>&1 | grep total 2>&1"
+	}
+	my ($du_exit_status, $du_output) = run_command($du_command);
+	
+	# If the partner doesn't have the image, a "no such file" error should be displayed
+	my $image_files_exist;
+	if (defined(@$du_output) && grep(/no such file/i, @$du_output)) {
+		notify($ERRORS{'OK'}, 0, "$image_name does NOT exist");
+		$image_files_exist = 0;
+	}
+	elsif (defined(@$du_output) && !grep(/\d+\s+total/i, @$du_output)) {
+		notify($ERRORS{'WARNING'}, 0, "du output does not contain a total line:\n" . join("\n", @$du_output));
+		return;
+	}
+	elsif (!defined($du_exit_status)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if image $image_name exists");
+		return;
+	}
+	
+	# Return 1 if the image size > 0
+	my ($image_size) = (@$du_output[0] =~ /(\d+)\s+total/);
+	if ($image_size && $image_size > 0) {
+		my $image_size_mb = int($image_size / 1024);
+		notify($ERRORS{'DEBUG'}, 0, "$image_name exists in $image_repository_path, size: $image_size_mb MB");
+		$image_files_exist = 1;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "image does NOT exist: $image_name");
+		$image_files_exist = 0;
+	}
 
+	# Image files exist, make sure template (.tmpl) file exists
 	# Get the tmpl repository path
 	my $tmpl_repository_path = $self->_get_image_template_path();
 	if (!$tmpl_repository_path) {
-		notify($ERRORS{'WARNING'}, 0, "image template path could not be determined");
+		notify($ERRORS{'WARNING'}, 0, "image template path could not be determined for $image_name");
 		return;
 	}
 	else {
-		notify($ERRORS{'DEBUG'}, 0, "template repository path: $tmpl_repository_path");
+		notify($ERRORS{'DEBUG'}, 0, "template repository path for $image_name: $tmpl_repository_path");
 	}
-
+	
 	# Check if template file exists for the image
 	# -s File has nonzero size
 	my $tmpl_file_exists;
@@ -2891,35 +2962,12 @@
 		$tmpl_file_exists = 0;
 		notify($ERRORS{'DEBUG'}, 0, "template file does not exist: $tmpl_repository_path/$image_name.tmpl");
 	}
-
-	# Check if image files exist (Partimage files)
-	# Open the repository directory
-	if (!opendir(REPOSITORY, $image_repository_path)) {
-		notify($ERRORS{'WARNING'}, 0, "unable to open the image repository directory: $image_repository_path");
-		return;
-	}
-
-	# Get the list of files in the repository and close the directory
-	my @repository_files = readdir(REPOSITORY);
-	closedir(REPOSITORY);
-
-	# Check if any files exist for the image
-	my $image_files_exist;
-	if (my @image_files = grep(/$image_name/, @repository_files)) {
-		$image_files_exist = 1;
-		my $image_file_list = join(@image_files, "\n");
-		notify($ERRORS{'DEBUG'}, 0, "image files exist in repository:\n$image_file_list");
-	}
-	else {
-		$image_files_exist = 0;
-		notify($ERRORS{'DEBUG'}, 0, "image files do not exist in repository: $image_repository_path/$image_name");
-	}
-
+	
 	# Check if either tmpl file or image files exist, but not both
 	# Attempt to correct the situation:
 	#    tmpl file exists but not image files: delete tmpl file
 	#    image files exist but not tmpl file: create tmpl file
-	if ($tmpl_file_exists && !$image_files_exist) {
+	if ($tmpl_file_exists && !$image_files_exist && $image_os_install_type ne 'kickstart') {
 		notify($ERRORS{'WARNING'}, 0, "template file exists but image files do not for $image_name");
 
 		# Attempt to delete the orphaned tmpl file for the image
@@ -2932,7 +2980,7 @@
 			return;
 		}
 	} ## end if ($tmpl_file_exists && !$image_files_exist)
-	elsif (!$tmpl_file_exists && $image_files_exist) {
+	elsif (!$tmpl_file_exists && $image_files_exist && $image_os_install_type ne 'kickstart') {
 		notify($ERRORS{'WARNING'}, 0, "image files exist but template file does not for $image_name");
 
 		# Attempt to create the missing tmpl file for the image
@@ -2952,7 +3000,7 @@
 		return 1;
 	}
 	else {
-		notify($ERRORS{'DEBUG'}, 0, "image $image_name does not exist on this management node");
+		notify($ERRORS{'DEBUG'}, 0, "image $image_name does NOT exist on this management node");
 		return 0;
 	}
 
@@ -2963,8 +3011,10 @@
 =head2 retrieve_image
 
  Parameters  : Image name (optional)
- Returns     :
- Description : Attempts to retrieve an image from an image library partner
+ Returns     : If successful: true (1)
+               If failed: false (undefined)
+ Description : Attempts to retrieve an image from an image library partner and
+               creates an xCAT template (.tmpl) file for the image.
 
 =cut
 
@@ -2982,7 +3032,8 @@
 		return;
 	}
 
-	# Get the image name
+	# If an argument was specified, use it as the image name
+	# If not, get the image name from the reservation data
 	my $image_name = shift || $self->data->get_image_name();
 	if (!$image_name) {
 		notify($ERRORS{'WARNING'}, 0, "unable to determine image name from argument or reservation data");
@@ -2991,83 +3042,104 @@
 	
 	# Make sure image does not already exist on this management node
 	if ($self->does_image_exist($image_name)) {
-		notify($ERRORS{'WARNING'}, 0, "image $image_name already exists on this management node");
+		notify($ERRORS{'OK'}, 0, "$image_name already exists on this management node");
 		return 1;
 	}
 
-	# Get the other image library variables
-	my $image_repository_path_local = $self->_get_image_repository_path()          || 'undefined';
-	my $image_lib_partners = $self->data->get_management_node_image_lib_partners() || 'undefined';
-	
-	if ("$image_repository_path_local $image_lib_partners" =~ /undefined/) {
-		notify($ERRORS{'WARNING'}, 0, "image library configuration data is missing:
-			local image repository path=$image_repository_path_local
-			partners=$image_lib_partners
-		");
+	# Get the image library partner string
+	my $image_lib_partners = $self->data->get_management_node_image_lib_partners();
+	if (!$image_lib_partners) {
+		notify($ERRORS{'WARNING'}, 0, "image library partners could not be determined");
 		return;
 	}
-
-	# Attempt to copy image from other management nodes
-	notify($ERRORS{'OK'}, 0, "attempting to retrieve image $image_name from another management node");
-
+	
 	# Split up the partner list
 	my @partner_list = split(/,/, $image_lib_partners);
 	if ((scalar @partner_list) == 0) {
 		notify($ERRORS{'WARNING'}, 0, "image lib partners variable is not listed correctly or does not contain any information: $image_lib_partners");
 		return;
 	}
-
-	# Loop through the partners, attempt to copy
+	
+	# Get the local image repository path
+	my $image_repository_path_local = $self->_get_image_repository_path();
+	if (!$image_repository_path_local) {
+		notify($ERRORS{'WARNING'}, 0, "image repository path could not be determined");
+		return;
+	}
+	
+	# Loop through the partners
+	# Find partners which have the image
+	# Check size for each partner
+	# Retrieve image from partner with largest image
+	# It's possible that another partner (management node) is currently copying the image from another managment node
+	# This should prevent copying a partial image
+	my $largest_partner;
+	my $largest_partner_hostname;
+	my $largest_partner_image_lib_user;
+	my $largest_partner_image_lib_key;
+	my $largest_partner_ssh_port;
+	my $largest_partner_path;
+	my $largest_partner_size = 0;
+	
+	notify($ERRORS{'OK'}, 0, "attempting to find another management node that contains $image_name");
 	foreach my $partner (@partner_list) {
-		# If another management node's repo path was requested, run find via ssh
-		my $management_node_hostname = $self->data->get_management_node_hostname($partner) || '';
-		my $management_node_image_lib_user = $self->data->get_management_node_image_lib_user($partner) || '';
-		my $management_node_image_lib_key = $self->data->get_management_node_image_lib_key($partner) || '';
-		my $management_node_ssh_port = $self->data->get_management_node_ssh_port($partner) || '';
+		# Get the connection information for the partner management node
+		my $partner_hostname = $self->data->get_management_node_hostname($partner) || '';
+		my $partner_image_lib_user = $self->data->get_management_node_image_lib_user($partner) || '';
+		my $partner_image_lib_key = $self->data->get_management_node_image_lib_key($partner) || '';
+		my $partner_ssh_port = $self->data->get_management_node_ssh_port($partner) || '';
 		my $image_repository_path_remote = $self->_get_image_repository_path($partner);
 		
-		notify($ERRORS{'OK'}, 0, "checking if $management_node_hostname has image $image_name");
+		notify($ERRORS{'OK'}, 0, "checking if $partner_hostname has image $image_name");
 		notify($ERRORS{'DEBUG'}, 0, "remote image repository path on $partner: $image_repository_path_remote");
 		
-		# Use ssh to call ls on the partner management node
-		my ($ls_exit_status, $ls_output) = run_ssh_command($partner, $management_node_image_lib_key, "ls -lh $image_repository_path_remote", $management_node_image_lib_user, $management_node_ssh_port, 1);
-		if (defined($ls_output) && grep(/$image_name/, @$ls_output)) {
-			notify($ERRORS{'OK'}, 0, "image $image_name exists on $management_node_hostname");
-		}
-		elsif (defined($ls_exit_status) && $ls_exit_status == 0) {
-			notify($ERRORS{'OK'}, 0, "image $image_name does NOT exist on $management_node_hostname");
-			next;
-		}
-		elsif (defined($ls_output) && grep(/No such file or directory/, @$ls_output)) {
-			notify($ERRORS{'OK'}, 0, "image repository path '$image_repository_path_remote' does not exist on $management_node_hostname");
+		# Run du to get the size of the image files on the partner if the image exists
+		my ($du_exit_status, $du_output) = run_ssh_command($partner, $partner_image_lib_key, "du -c $image_repository_path_remote/*$image_name* | grep total", $partner_image_lib_user, $partner_ssh_port, 1);
+		
+		# If the partner doesn't have the image, a "no such file" error should be displayed
+		if (defined(@$du_output) && grep(/no such file/i, @$du_output)) {
+			notify($ERRORS{'OK'}, 0, "$image_name does NOT exist on $partner_hostname");
 			next;
 		}
-		elsif (defined($ls_exit_status)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to determine if image $image_name exists on $management_node_hostname, exit status: $ls_exit_status, output:\n" . join("\n", @$ls_output));
+		elsif (defined(@$du_output) && !grep(/\d+\s+total/i, @$du_output)) {
+			notify($ERRORS{'WARNING'}, 0, "du output does not contain a total line:\n" . join("\n", @$du_output));
 			next;
 		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if image $image_name exists on $management_node_hostname");
+		elsif (!defined($du_exit_status)) {
+			notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to determine if image $image_name exists on $partner_hostname");
 			next;
 		}
 		
-		# Attempt copy
-		notify($ERRORS{'OK'}, 0, "copying image $image_name from $management_node_hostname");
-		if (run_scp_command("$management_node_image_lib_user\@$partner:$image_repository_path_remote/$image_name*", $image_repository_path_local, $management_node_image_lib_key, $management_node_ssh_port)) {
-			notify($ERRORS{'OK'}, 0, "image $image_name was copied from $management_node_hostname");
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "failed to copy image $image_name from $management_node_hostname");
-			next;
-		}
+		# Extract the image size in bytes from the du total output line
+		my ($partner_image_size) = (@$du_output[0] =~ /(\d+)\s+total/);
+		notify($ERRORS{'OK'}, 0, "$image_name exists on $partner_hostname, size: $partner_image_size bytes");
 		
-		# Create the template file for the image
-		if (!$self->_create_template()) {
-			notify($ERRORS{'WARNING'}, 0, "failed to create template file for image $image_name");
-			return;
+		# Check if the image size is larger than any previously found, if so, save the partner info
+		if ($partner_image_size > $largest_partner_size) {
+			$largest_partner = $partner;
+			$largest_partner_hostname = $partner_hostname;
+			$largest_partner_size = $partner_image_size;
+			$largest_partner_image_lib_user = $partner_image_lib_user;
+			$largest_partner_image_lib_key = $partner_image_lib_key;
+			$largest_partner_ssh_port = $partner_ssh_port;
+			$largest_partner_path = $image_repository_path_remote;
 		}
-		
-		last;
+	}
+	
+	# Check if any partner was found
+	if (!$largest_partner) {
+		notify($ERRORS{'WARNING'}, 0, "unable to find $image_name on other management nodes");
+		return;
+	}
+	
+	# Attempt copy
+	notify($ERRORS{'OK'}, 0, "attempting to retrieve $image_name from $largest_partner_hostname");
+	if (run_scp_command("$largest_partner_image_lib_user\@$largest_partner:$largest_partner_path/$image_name*", $image_repository_path_local, $largest_partner_image_lib_key, $largest_partner_ssh_port)) {
+		notify($ERRORS{'OK'}, 0, "image $image_name was copied from $largest_partner_hostname");
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to copy image $image_name from $largest_partner_hostname");
+		next;
 	}
 	
 	# Make sure image was copied
@@ -3075,9 +3147,15 @@
 		notify($ERRORS{'WARNING'}, 0, "$image_name was not copied to this management node");
 		return 0;
 	}
-
+	
+	# Create the template file for the image
+	if (!$self->_create_template()) {
+		notify($ERRORS{'WARNING'}, 0, "failed to create template file for image: $image_name");
+		return;
+	}
+	
 	return 1;
-} ## end sub retrieve_image
+}
 
 #/////////////////////////////////////////////////////////////////////////////
 
@@ -3256,6 +3334,7 @@
 		notify($ERRORS{'DEBUG'}, 0, "management node identifier argument was not specified");
 	}
 	
+	my $management_node_hostname = $self->data->get_management_node_hostname($management_node_identifier) || '';
 	my $management_node_install_path = $self->data->get_management_node_install_path($management_node_identifier);
 	
 	# Get required image data
@@ -3265,6 +3344,7 @@
 	my $image_os_install_type    = $self->data->get_image_os_install_type() || 'undefined';
 	my $image_os_source_path     = $self->data->get_image_os_source_path() || 'undefined';
 	my $image_architecture       = $self->data->get_image_architecture() || 'undefined';
+	
 	if ("$image_os_name $image_os_type $image_os_install_type $image_os_source_path $image_architecture" =~ /undefined/) {
 		notify($ERRORS{'WARNING'}, 0, "some of the required data could not be retrieved: OS name=$image_os_name, OS type=$image_os_type, OS install type=$image_os_install_type, OS source path=$image_os_source_path, architecture=$image_architecture");
 		return;
@@ -3273,7 +3353,7 @@
 	# Remove trailing / from $image_os_source_path if exists
 	$image_os_source_path =~ s/\/$//;
 	
-	notify($ERRORS{'DEBUG'}, 0, "attempting to determine repository path for image:
+	notify($ERRORS{'DEBUG'}, 0, "attempting to determine repository path for image on $management_node_hostname:
 		image id:        $image_id
 		OS name:         $image_os_name
 		OS type:         $image_os_type
@@ -3296,7 +3376,7 @@
 	# Note: $image_install_path has a leading /
 	if ($image_os_install_type eq 'kickstart') {
 		# Kickstart installs use the xCAT path for both repo and tmpl paths
-		my $kickstart_repo_path = "$XCAT_ROOT$image_install_path/$image_architecture";
+		my $kickstart_repo_path = "$image_install_path/$image_architecture";
 		notify($ERRORS{'DEBUG'}, 0, "kickstart install type, returning $kickstart_repo_path");
 		return $kickstart_repo_path;
 	}
@@ -3315,13 +3395,11 @@
 		}
 		else {
 			# If another management node's repo path was requested, run find via ssh
-			my $management_node_hostname = $self->data->get_management_node_hostname($management_node_identifier) || '';
 			my $management_node_image_lib_user = $self->data->get_management_node_image_lib_user($management_node_identifier) || '';
 			my $management_node_image_lib_key = $self->data->get_management_node_image_lib_key($management_node_identifier) || '';
 			my $management_node_ssh_port = $self->data->get_management_node_ssh_port($management_node_identifier) || '';
 			
-			notify($ERRORS{'DEBUG'}, 0, "attempting to find linux images under '$linux_image_repo_path' on management node:
-					 hostname=$management_node_hostname
+			notify($ERRORS{'DEBUG'}, 0, "attempting to find linux images under '$linux_image_repo_path' on $management_node_hostname:
 					 user=$management_node_image_lib_user
 					 key=$management_node_image_lib_key
 					 port=$management_node_ssh_port
@@ -3335,21 +3413,21 @@
 		if ($find_output) {
 			my $linux_images_found = grep(/\.gz/, @$find_output);
 			if ($linux_images_found) {
-				notify($ERRORS{'DEBUG'}, 0, "found $linux_images_found images, returning $linux_image_repo_path");
+				notify($ERRORS{'DEBUG'}, 0, "found $linux_images_found images on $management_node_hostname, returning $linux_image_repo_path");
 				return $linux_image_repo_path;
 			}
 			else {
-				notify($ERRORS{'DEBUG'}, 0, "did not find any images under $linux_image_repo_path");
+				notify($ERRORS{'DEBUG'}, 0, "did not find any images under $linux_image_repo_path on $management_node_hostname");
 			}
 		}
 		else {
-			notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to run find");
+			notify($ERRORS{'WARNING'}, 0, "failed to run ssh command to run find on $management_node_hostname");
 		}
 		
 	}
 	
 	my $repo_path = "$image_install_path/$image_architecture";
-	notify($ERRORS{'DEBUG'}, 0, "returning: $repo_path");
+	notify($ERRORS{'DEBUG'}, 0, "returning repository path for $management_node_hostname: $repo_path");
 	return $repo_path;
 } ## end sub _get_image_repository_path
 

Modified: incubator/vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=794283&r1=794282&r2=794283&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/utils.pm Wed Jul 15 14:30:16 2009
@@ -122,7 +122,6 @@
   get_image_info
   get_imagemeta_info
   get_imagerevision_info
-  get_ip_address_from_hosts
   get_management_node_blockrequests
   get_management_node_id
   get_management_node_info
@@ -145,6 +144,7 @@
   insert_reload_request
   insert_request
   insertloadlog
+  is_management_node_process_running
   is_inblockrequest
   is_request_deleted
   is_request_imaging
@@ -6673,8 +6673,8 @@
 		#    Offending key for IP in /root/.ssh/known_hosts:264
 		#    Matching host key in /root/.ssh/known_hosts:3977
 		$ssh_output =~ s/^Warning:.*//ig;
-		$ssh_output =~ s/^Offending key.*//ig;
-		$ssh_output =~ s/^Matching host key in.*//ig;
+		$ssh_output =~ s/Offending key.*//ig;
+		$ssh_output =~ s/Matching host key in.*//ig;
 		
 		# Remove any spaces from the beginning and end of the output
 		$ssh_output =~ s/(^\s+)|(\s+$)//g;
@@ -8658,112 +8658,6 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 get_ip_address_from_hosts
-
- Parameters  : $host_name
- Returns     : IP address of specified node if successful, 0 if failed
- Description : Searches the local hosts file for a line containing the host
-               name specified. Returns the corresponding IP address.
-
-=cut
-
-sub get_ip_address_from_hosts {
-	my ($host_name) = @_;
-	my ($package, $filename, $line, $sub) = caller(0);
-
-	# Check the argument
-	if (!defined($host_name) || !$host_name) {
-		notify($ERRORS{'WARNING'}, 0, "computer host name was not specified");
-		return 0;
-	}
-
-	# Check the OS of the machine running this, set the hosts file accordingly
-	my $hosts_file_path;
-	if (lc($^O) =~ /win/i) {
-		$hosts_file_path = $ENV{SystemRoot} . '\\system32\\drivers\\etc\\hosts';
-	}
-	else {
-		$hosts_file_path = '/etc/hosts';
-	}
-
-	# Retrieve the node's private IP address from the hosts file
-	# Try to open the hosts file
-	if (open(HOSTS, $hosts_file_path)) {
-		notify($ERRORS{'OK'}, 0, "opened hosts file: $hosts_file_path") if $VERBOSE;
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "unable to open the hosts file: $hosts_file_path");
-		return 0;
-	}
-
-	# Find all lines in the hosts file containing the host name
-	# Make sure the host name has a space in front of it so that host1 != xhost1
-	# If host name being searched for is followed by a space or period, ignore rest of line
-	#   This accounts for full DNS host names, host1.unity...
-	# If host name isn't followed by space or period, make sure the end of sting is immediately following
-	#   This accounts for host1 != host1x
-	# This also accounts for the end of file immediately following the host name
-	my @hosts_matching_lines = grep(/\s$host_name([\s\.].*)*$/i, <HOSTS>);
-
-	# Close the HOSTS file
-	close HOSTS;
-
-	# Make sure only 1 line was returned
-	if (scalar @hosts_matching_lines == 0) {
-		notify($ERRORS{'WARNING'}, 0, "unable to find line containing $host_name in hosts file");
-		return 0;
-	}
-	elsif (scalar @hosts_matching_lines > 1) {
-		notify($ERRORS{'OK'}, 0, "found " . scalar @hosts_matching_lines . " lines containing $host_name in hosts file, first valid match will be used");
-	}
-
-	# Find the IP address
-	my $ip_address;
-	for (@hosts_matching_lines) {
-		my $line = $_;
-		chomp $line;
-
-		# Check for IPv4 address pattern
-		if ($line =~ /^\s*(([0-9]{1,3}\.{0,1}){4})\s/) {
-			$ip_address = $1;
-			notify($ERRORS{'OK'}, 0, "found IPv4 address: $ip_address") if $VERBOSE;
-		}
-		# Check for IPv6 address pattern
-		elsif ($line =~ /^\s*(([0-9a-f]{0,4}:{0,2}){1,8})\s/i) {
-			$ip_address = $1;
-			notify($ERRORS{'OK'}, 0, "found IPv6 address: $ip_address") if $VERBOSE;
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "hosts file line does not contain a valid IP address: $line");
-			next;
-		}
-
-		# Check if the line is a comment
-		if ($line =~ /^\s*#/) {
-			notify($ERRORS{'OK'}, 0, "host name found in commented line: $line");
-			# Proceed to try other matches, hoping for a non-commented match
-			next;
-		}
-		else {
-			# Line is not commented, return the IP address
-			return $ip_address;
-		}
-	} ## end for (@hosts_matching_lines)
-
-	# Check if an IP address was found
-	if ($ip_address) {
-		# This should only happen if the host name was found in a commented line
-		return $ip_address;
-	}
-	else {
-		# Address was not found
-		notify($ERRORS{'WARNING'}, 0, "unable to find any valid matching address in hosts file");
-		return 0;
-	}
-} ## end sub get_ip_address_from_hosts
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 firewall_compare_update
 
  Parameters  : $node,$reote_IP, $identity, $type
@@ -10526,6 +10420,51 @@
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 is_management_node_process_running
+
+ Parameters  : PID or process name
+ Returns     : 0 or 1
+ Description : 
+
+=cut
+
+sub is_management_node_process_running {
+	my ($process_identifier) = @_;
+	
+	# Check the arguments
+	unless ($process_identifier) {
+		notify($ERRORS{'WARNING'}, 0, "process PID or name argument was not specified");
+		return;
+	}
+	
+	my @pids;
+	my $command = "pgrep -fl \"$process_identifier\"";
+	my ($exit_status, $output) = run_command($command, 1);
+	my @filtered_output;
+	@filtered_output = grep(!/sh -c/, @$output) if @$output;
+	if (@filtered_output) {
+		notify($ERRORS{'DEBUG'}, 0, "process is running, identifier: $process_identifier, pgrep output:\n" . join("\n", @filtered_output));
+		
+		for my $pgrep_line (@filtered_output) {
+			my ($pid) = $pgrep_line =~ /^(\d+)/;
+			push @pids, $pid;
+		}
+		
+		notify($ERRORS{'DEBUG'}, 0, "returning pid array: @pids");
+		return @pids;
+	}
+	elsif (defined($exit_status)) {
+		notify($ERRORS{'DEBUG'}, 0, "process is NOT running, identifier: $process_identifier, pgrep output:\n" . join("\n", @$output));
+		return ();
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to run command to determine if process is running");
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 1;
 __END__