Author: arkurth
Date: Tue Aug 30 18:22:57 2016
New Revision: 1758437

URL: http://svn.apache.org/viewvc?rev=1758437&view=rev
Log:
VCL-987
Extended xCAT.pm::get_image_repository_directory_path to attempt to locate a 
suitable Linux Kickstart directory if the default location does not exist.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm?rev=1758437&r1=1758436&r2=1758437&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm Tue Aug 30 
18:22:57 2016
@@ -65,6 +65,7 @@ use Fcntl qw(:DEFAULT :flock);
 use File::Copy;
 use IO::Seekable;
 use Socket;
+use version;
 
 ##############################################################################
 
@@ -858,6 +859,30 @@ sub get_image_size {
                node. Examples:
                Partimage image: /install/image/x86
                Kickstart image: /install/centos5/x86_64
+               
+               The path is constructed from the following database values:
+               * managementnode.installpath
+               * OS.sourcepath
+               * image.architecture
+               
+               If a directory exactly matching OS.sourcepath cannot be located
+               on the managementnode node, an attempt is made to locate an
+               alternate suitable directory matching the distribution and major
+               version. Example, if OS.sourcepath = 'rhel7' and the following
+               directory does not exist:
+               /install/rhel7/x86_64
+               
+               Any of the following paths which exist on the management node 
may
+               be returned:
+               /install/rhel7.1/x86_64
+               /install/rhels7.2/x86_64
+               /install/rhels7.10/x86_64
+               
+               If all of these paths exist, the path with the highest version 
is
+               returned:
+               /install/rhels7.10/x86_64
+               
+               Note: for 'rhel', both 'rhel' and 'rhels' are checked.
 
 =cut
 
@@ -870,66 +895,164 @@ sub get_image_repository_directory_path
        
        # Get the image name argument
        my $image_name = shift || $self->data->get_image_name();
-       if (!$image_name) {
-               notify($ERRORS{'WARNING'}, 0, "image name argument was not 
specified");
-               return;
-       }
-
+       
+       my $local_management_node_hostname = 
$self->data->get_management_node_hostname();
+       my $management_node_hostname;
+       
        # Check if a management node identifier argument was passed
        my $management_node_identifier = shift;
        if ($management_node_identifier) {
-               notify($ERRORS{'DEBUG'}, 0, "management node identifier 
argument was specified: $management_node_identifier");
+               $management_node_hostname = 
$self->data->get_management_node_hostname($management_node_identifier);
+               if ($management_node_hostname) {
+                       notify($ERRORS{'DEBUG'}, 0, "management node identifier 
argument was specified: $management_node_identifier, hostname: 
$management_node_hostname");
+               }
+               else {
+                       notify($ERRORS{'WARNING'}, 0, "management node hostname 
could not be determined from argument: $management_node_identifier");
+                       return;
+               }
+       }
+       else {
+               $management_node_hostname = $local_management_node_hostname;
+       }
+       
+       # Check if path has already been determined
+       if 
(defined($self->{image_repository_path}{$image_name}{$management_node_hostname}))
 {
+               return 
$self->{image_repository_path}{$image_name}{$management_node_hostname};
        }
        
-       my $management_node_hostname = 
$self->data->get_management_node_hostname($management_node_identifier) || '';
-       return 
$self->{image_repository_path}{$image_name}{$management_node_hostname} if 
defined($self->{image_repository_path}{$image_name}{$management_node_hostname});
        my $management_node_install_path = 
$self->data->get_management_node_install_path($management_node_identifier);
        
        # Create a DataStructure object containing info about the image
        my $image_data = $self->create_datastructure_object({image_identifier 
=> $image_name}) || return;
-       my $image_id = $image_data->get_image_id() || return;
-       my $image_os_name = $image_data->get_image_os_name() || return;
-       my $image_os_type = $image_data->get_image_os_type() || return;
-       my $image_os_install_type = $image_data->get_image_os_install_type() || 
return;
-       my $image_os_source_path = $image_data->get_image_os_source_path() || 
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;
        
-       # Remove trailing / from $image_os_source_path if exists
-       $image_os_source_path =~ s/\/$//;
+       # Remove trailing / from $management_node_install_path if exists
+       $management_node_install_path =~ s/\/+$//;
        
-       #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
-       #       OS install type: $image_os_install_type
-       #       OS source path:  $image_os_source_path\n
-       #       architecture:    $image_architecture
-       #");
+       # Remove trailing / from $os_source_path if exists
+       $os_source_path =~ s/\/+$//;
+
+       notify($ERRORS{'DEBUG'}, 0, "attempting to determine repository path 
for image on $management_node_hostname:\n" .
+               "install path    : $management_node_install_path\n" .
+               "image name      : $image_name\n" .
+               "OS install type : $os_install_type\n" .
+               "OS source path  : $os_source_path\n" .
+               "architecture    : $image_architecture"
+       );
        
        # If image OS source path has a leading /, assume it was meant to be 
absolute
        # Otherwise, prepend the install path
        my $image_install_path;
-       if ($image_os_source_path =~ /^\//) {
-               $image_install_path = $image_os_source_path;
+       if ($os_source_path =~ /^\//) {
+               $image_install_path = $os_source_path;
        }
        else {
-               $image_install_path = 
"$management_node_install_path/$image_os_source_path";
+               $image_install_path = 
"$management_node_install_path/$os_source_path";
        }
 
        # Note: $XCAT_ROOT has a leading /
        # Note: $image_install_path has a leading /
-       if ($image_os_install_type eq 'kickstart') {
+       if ($os_install_type eq 'kickstart') {
                # Kickstart installs use the xCAT path for both repo and tmpl 
paths
-               my $kickstart_repo_path = 
"$image_install_path/$image_architecture";
-               $self->{image_repository_path}{$management_node_hostname} = 
$kickstart_repo_path;
-               notify($ERRORS{'DEBUG'}, 0, "kickstart install type, returning 
$kickstart_repo_path");
-               return $kickstart_repo_path;
+               my $kickstart_repository_path = 
"$image_install_path/$image_architecture";
+               
+               # If retrieving directory path for local management node, check 
if it exists
+               # xCAT's copycds command will use something like a 
/install/rhels6.6 directory
+               # os.sourcepath may be 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 ($management_node_hostname eq 
$local_management_node_hostname) {
+                       if 
(!$self->mn_os->file_exists($kickstart_repository_path)) {
+                               # Parse the version of the requested OS
+                               my ($os_distribution, $os_version_string, 
$major_os_version_string) = $os_source_path =~ /^([a-z]+)((\d+)[\d\.]*)$/ig;
+                               if (!defined($os_distribution) || 
!defined($os_version_string) || !defined($major_os_version_string)) {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to locate repository directory path on the local management node for kickstart 
image $image_name, the OS.sourcepath could not be parsed: $os_source_path, 
returning default path: $kickstart_repository_path");
+                                       
$self->{image_repository_path}{$management_node_hostname} = 
$kickstart_repository_path;
+                                       return $kickstart_repository_path;
+                               }
+                               notify($ERRORS{'DEBUG'}, 0, "kickstart 
repository path based on the OS.sourcepath value '$os_source_path' does not 
exist: $kickstart_repository_path, attempting to locate another suitable path 
matching distribution: $os_distribution, version: $os_version_string, major 
version: $major_os_version_string");
+                               
+                               
+                               my @matching_distribution_paths = 
$self->mn_os->find_files($management_node_install_path, "*", 0, 'd');
+                               my $highest_matching_version_string;
+                               my $highest_kickstart_repository_path;
+                               for my $matching_distribution_path 
(@matching_distribution_paths) {
+                                       my $os_distribution_regex = 
$os_distribution;
+                                       if ($os_distribution =~ /rhel/) {
+                                               # Match 'rhel' and 'rhels'
+                                               $os_distribution_regex = 
'rhels?';
+                                       }
+                                       
+                                       if ($matching_distribution_path !~ 
/$os_distribution_regex/) {
+                                               #notify($ERRORS{'DEBUG'}, 0, 
"ignoring directory, it does not match the OS distribution regex 
'$os_distribution_regex': $matching_distribution_path");
+                                               next;
+                                       }
+                                       
+                                       
+                                       my ($matching_version_string, 
$matching_major_version_string) = $matching_distribution_path =~ 
/$os_distribution_regex((\d+)[\d\.]*)/;
+                                       if (!defined($matching_version_string) 
|| !defined($matching_major_version_string)) {
+                                               notify($ERRORS{'DEBUG'}, 0, 
"ignoring directory, version could not be determined: 
$matching_distribution_path");
+                                               next;
+                                       }
+                                       
+                                       
+                                       # Make sure the major version matches
+                                       if ($matching_major_version_string ne 
$major_os_version_string) {
+                                               notify($ERRORS{'DEBUG'}, 0, 
"distribution directory ignored, major version $matching_major_version_string 
does not match requested major version $major_os_version_string: 
$matching_distribution_path");
+                                               next;
+                                       }
+                                       
+                                       # Make sure the correct architecture 
subdirectory exists
+                                       my $matching_kickstart_repository_path 
= "$matching_distribution_path/$image_architecture";
+                                       if 
(!$self->mn_os->file_exists($matching_kickstart_repository_path)) {
+                                               notify($ERRORS{'DEBUG'}, 0, 
"ignoring directory becuase $image_architecture subdirectory does not exist: 
$matching_distribution_path");
+                                               next;
+                                       }
+                                       
+                                       if (!$highest_matching_version_string) {
+                                               notify($ERRORS{'DEBUG'}, 0, 
"1st matching distribution directory is possibly an alternate path: 
$matching_kickstart_repository_path, version: $matching_version_string");
+                                               
$highest_kickstart_repository_path = $matching_kickstart_repository_path;
+                                               
$highest_matching_version_string = $matching_version_string;
+                                               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("$matching_version_string")->numify;
+                                       my $highest_matching_version_numified = 
version->declare("$highest_matching_version_string")->numify;
+                                       if ($highest_matching_version_numified 
> $matching_version_numified) {
+                                               notify($ERRORS{'DEBUG'}, 0, 
"distribution directory ignored, version $matching_version_string 
($matching_version_numified) is less than $highest_matching_version_string 
($highest_matching_version_numified): $matching_distribution_path");
+                                               next;
+                                       }
+                                       else {
+                                               notify($ERRORS{'DEBUG'}, 0, 
"distribution directory version $matching_version_string 
($matching_version_numified) is greater than $highest_matching_version_string 
($highest_matching_version_numified): $matching_kickstart_repository_path");
+                                               
$highest_kickstart_repository_path = $matching_kickstart_repository_path;
+                                               
$highest_matching_version_string = $matching_version_string;
+                                               next;
+                                       }
+                               }
+                               
+                               if ($highest_kickstart_repository_path) {
+                                       notify($ERRORS{'OK'}, 0, "located 
alternate repository directory path on the local management node for kickstart 
image $image_name: $highest_kickstart_repository_path");
+                                       $kickstart_repository_path = 
$highest_kickstart_repository_path;
+                               }
+                               else {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to locate repository directory path on the local management node for kickstart 
image $image_name, the OS.sourcepath could not be parsed: $os_source_path, 
returning default path: $kickstart_repository_path");
+                               }
+                       }
+               }
+               
+               $self->{image_repository_path}{$management_node_hostname} = 
$kickstart_repository_path;
+               notify($ERRORS{'DEBUG'}, 0, "kickstart install type, returning 
$kickstart_repository_path");
+               return $kickstart_repository_path;
+       }
+       else {
+               my $repo_path = "$image_install_path/$image_architecture";
+               
$self->{image_repository_path}{$image_name}{$management_node_hostname} = 
$repo_path;
+               notify($ERRORS{'DEBUG'}, 0, "returning repository path for 
$management_node_hostname: $repo_path");
+               return $repo_path;
        }
-       
-       my $repo_path = "$image_install_path/$image_architecture";
-       $self->{image_repository_path}{$image_name}{$management_node_hostname} 
= $repo_path;
-       notify($ERRORS{'DEBUG'}, 0, "returning repository path for 
$management_node_hostname: $repo_path");
-       return $repo_path;
 } ## end sub get_image_repository_directory_path
 
 #/////////////////////////////////////////////////////////////////////////////


Reply via email to