sub get_nodetype_image_os_name()

in managementnode/lib/VCL/Module/Provisioning/xCAT.pm [895:1051]


sub get_nodetype_image_os_name {
	my $self = shift;
	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 argument
	my $image_name = shift || $self->data->get_image_name();
	
	# Check if path has already been determined
	if (defined($self->{xcat_image_os_name}{$image_name})) {
		return $self->{xcat_image_os_name}{$image_name};
	}
	
	my $management_node_hostname = $self->data->get_management_node_hostname();
	my $management_node_install_path = $self->data->get_management_node_install_path() || return;
	
	# Create a DataStructure object containing info about the image
	my $image_data = $self->create_datastructure_object({image_identifier => $image_name}) || return;
	my $os_install_type    = $image_data->get_image_os_install_type() || return;
	my $os_source_path     = $image_data->get_image_os_source_path() || return;
	my $image_architecture = $image_data->get_image_architecture() || return;
	
	if ($os_install_type =~ /image/i) {
		notify($ERRORS{'DEBUG'}, 0, "OS install type for image $image_name is $os_install_type, returning 'image'");
		$self->{xcat_image_os_name}{$image_name} = 'image';
		return 'image';
	}
	elsif ($os_install_type !~ /(kickstart|netboot)/) {
		notify($ERRORS{'WARNING'}, 0, "unable to determine nodetype image OS name for image $image_name, OS install type is not supported: $os_install_type");
		return;
	}
	
	# Remove trailing / from $management_node_install_path if exists
	$management_node_install_path =~ s/\/+$//g;
	
	# Remove leading and trailing slashes from $os_source_path if exists
	$os_source_path =~ s/^\/+//g;
	$os_source_path =~ s/\/+$//g;

	notify($ERRORS{'DEBUG'}, 0, "attempting to determine nodetype OS name for image on $management_node_hostname:\n" .
		"image name      : $image_name\n" .
		"OS install type : $os_install_type\n" .
		"install path    : $management_node_install_path\n" .
		"OS source path  : $os_source_path\n" .
		"architecture    : $image_architecture"
	);
	
	my $installation_repository_directory_path = "$management_node_install_path/$os_source_path/$image_architecture";
	
	# Check if the default path exists - it's often named something different
	# xCAT's copycds command will use something like /install/rhels6.6
	# OS.sourcepath is probably set to rhel6
	# Creating a symlink doesn't work correctly because xCAT fails to parse directory names which don't contain a period correctly
	if ($self->mn_os->file_exists($installation_repository_directory_path)) {
		$self->{xcat_image_os_name}{$image_name} = $os_source_path;
		notify($ERRORS{'DEBUG'}, 0, "default installation repository directory exists: $installation_repository_directory_path, returning '$self->{xcat_image_os_name}{$image_name}'");
		return $self->{xcat_image_os_name}{$image_name};
	}
	
	# Parse the version of the requested OS source path
	my ($os_distribution_name, $os_version_string, $major_os_version_string) = $os_source_path =~ /^([a-z]+)((\d+)[\d\.]*)$/ig;
	if (!defined($os_distribution_name) || !defined($os_version_string) || !defined($major_os_version_string)) {
		$self->{xcat_image_os_name}{$image_name} = $os_source_path;
		notify($ERRORS{'WARNING'}, 0, "failed to determine nodetype OS name for image $image_name, OS.sourcepath could not be parsed: $os_source_path, returning default path: '$self->{xcat_image_os_name}{$image_name}'");
		return $self->{xcat_image_os_name}{$image_name};
	}
	
	notify($ERRORS{'DEBUG'}, 0, "default installation repository directory path does not exist: $installation_repository_directory_path, attempting to locate another suitable path matching distribution: $os_distribution_name, version: $os_version_string, major version: $major_os_version_string");
	
	# Fix regex for 'rhel' and 'rhels'
	my $os_distribution_regex = $os_distribution_name;
	if ($os_distribution_name =~ /rhel/) {
		$os_distribution_regex = 'rhels?';
	}
	
	my $highest_version_string;
	my $highest_version_directory_path;
	my $highest_version_nodetype_os_name;
	
	# Retrieve list of directories under the root management node install path
	my @check_directory_paths = $self->mn_os->find_files($management_node_install_path, "*", 0, 'd');
	for my $check_directory_path (@check_directory_paths) {
		# Remove trailing slash
		$check_directory_path =~ s/\/+$//g;
		
		next if $check_directory_path eq $management_node_install_path;
		
		# Ignore directories that don't contain the Linux OS distribution name
		if ($check_directory_path !~ /$os_distribution_regex/) {
			#notify($ERRORS{'DEBUG'}, 0, "ignoring directory: $check_directory_path, it does not match the pattern for the OS distribution: '$os_distribution_regex'");
			next;
		}
		
		my ($check_nodetype_os_name) = $check_directory_path =~ /\/([^\/]+)$/;
		if (!defined($check_nodetype_os_name)) {
			notify($ERRORS{'WARNING'}, 0, "ignoring directory: $check_directory_path, failed to parse directory name (nodetype OS name)");
			next;
		}
		
		# Parse the version and major version from the directory name
		my ($directory_version_string, $directory_major_version_string) = $check_directory_path =~ /$os_distribution_regex((\d+)[\d\.]*)/;
		if (!defined($directory_version_string) || !defined($directory_major_version_string)) {
			notify($ERRORS{'DEBUG'}, 0, "ignoring directory: $check_directory_path, version could not be determined");
			next;
		}
		
		# Make sure the major version matches
		if ($directory_major_version_string ne $major_os_version_string) {
			notify($ERRORS{'DEBUG'}, 0, "ignoring directory: $check_directory_path, major version $directory_major_version_string does not match requested major version $major_os_version_string");
			next;
		}
		
		# Make sure the correct architecture subdirectory exists
		my $check_installation_repository_directory_path = "$check_directory_path/$image_architecture";
		if (!$self->mn_os->file_exists($check_installation_repository_directory_path)) {
			notify($ERRORS{'DEBUG'}, 0, "ignoring directory: $check_directory_path, '$image_architecture' subdirectory does not exist");
			next;
		}
		
		if (!$highest_version_string) {
			notify($ERRORS{'DEBUG'}, 0, "1st matching directory is possibly an alternate path: $check_installation_repository_directory_path, version: $directory_version_string");
			$highest_version_string = $directory_version_string;
			$highest_version_directory_path = $check_installation_repository_directory_path;
			$highest_version_nodetype_os_name = $check_nodetype_os_name;
			next;
		}
		
		# Check if the version isn't less than one previously checked
		# Use version->declare->numify to correctly compare versions, otherwise 6.9 > 6.10
		my $matching_version_numified = version->declare("$directory_version_string")->numify;
		my $highest_matching_version_numified = version->declare("$highest_version_string")->numify;
		if ($matching_version_numified <= $highest_matching_version_numified) {
			notify($ERRORS{'DEBUG'}, 0, "directory ignored, version $directory_version_string ($matching_version_numified) is not higher than $highest_version_string ($highest_matching_version_numified): $check_directory_path");
			next;
		}
		else {
			notify($ERRORS{'DEBUG'}, 0, "directory version $directory_version_string ($matching_version_numified) is greater than $highest_version_string ($highest_matching_version_numified): $check_installation_repository_directory_path");
			$highest_version_string = $directory_version_string;
			$highest_version_directory_path = $check_installation_repository_directory_path;
			$highest_version_nodetype_os_name = $check_nodetype_os_name;
			next;
		}
	}
	
	if ($highest_version_nodetype_os_name) {
		$self->{xcat_image_os_name}{$image_name} = $highest_version_nodetype_os_name;
		notify($ERRORS{'OK'}, 0, "located alternate repository directory path on the local management node for kickstart image $image_name: $highest_version_directory_path, returning nodetype OS name: $self->{xcat_image_os_name}{$image_name}");
		return $self->{xcat_image_os_name}{$image_name};
	}
	else {
		$self->{xcat_image_os_name}{$image_name} = $os_source_path;
		notify($ERRORS{'WARNING'}, 0, "failed to locate repository directory path on the local management node for kickstart image $image_name, returning default nodetype OS name: $self->{xcat_image_os_name}{$image_name}");
		return $self->{xcat_image_os_name}{$image_name};
	}
}