Author: arkurth
Date: Tue Aug 30 20:18:52 2016
New Revision: 1758462

URL: http://svn.apache.org/viewvc?rev=1758462&view=rev
Log:
VCL-987
Pulled logic out of xCAT.pm::get_image_repository_directory_path to dedicated 
get_nodetype_image_os_name subroutine since it needs to be used elsewhere.

Added calls to get_nodetype_image_os_name in 
get_image_repository_directory_path and _edit_nodetype.

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=1758462&r1=1758461&r2=1758462&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/xCAT.pm Tue Aug 30 
20:18:52 2016
@@ -848,27 +848,33 @@ sub get_image_size {
 
 } ## end sub get_image_size
 
-
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 get_image_repository_directory_path
+=head2 get_nodetype_image_os_name
 
- Parameters  : $image_name, $management_node_identifier (optional)
+ Parameters  : $image_name
  Returns     : string
- Description : Determines the path where the image resides on the management
-               node. Examples:
-               Partimage image: /install/image/x86
-               Kickstart image: /install/centos5/x86_64
+ Description : Determines the name of the directory where installation files
+               should reside under the management node's install path.
+               Examples:
+                                       * image
+               * centos5
+                                       * rhels7.2
+                                       * ubuntu16.04.1
                
-               The path is constructed from the following database values:
-               * managementnode.installpath
-               * OS.sourcepath
-               * image.architecture
+                                       The path is determined by first 
checking if a directory exists
+                                       matching the database values:
+                                       * managementnode.installpath (ex: 
/install)
+                                       * OS.sourcepath (ex: rhel7)
+                                       * image.architecture (ex: x86_64)
+                                       
+                                       Based on these values, the default path 
will be:
+                                       /install/rhel7/x86_64
                
                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
+               version. Example, if OS.sourcepath = 'rhel7' and the default
                directory does not exist:
                /install/rhel7/x86_64
                
@@ -876,17 +882,17 @@ sub get_image_size {
                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
+               rhels7.2
                
                Note: for 'rhel', both 'rhel' and 'rhels' are checked.
 
 =cut
 
-sub get_image_repository_directory_path {
+
+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");
@@ -896,11 +902,180 @@ sub get_image_repository_directory_path
        # Get the image name argument
        my $image_name = shift || $self->data->get_image_name();
        
-       my $local_management_node_hostname = 
$self->data->get_management_node_hostname();
-       my $management_node_hostname;
+       # 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();
+       
+       # 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};
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_image_repository_directory_path
+
+ Parameters  : $image_name, $management_node_identifier (optional)
+ Returns     : string
+ Description : Determines the path where the image resides on the management
+               node. Examples:
+               Partimage image: /install/image/x86
+               Kickstart image: /install/centos5/x86_64
+
+=cut
+
+sub get_image_repository_directory_path {
+       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 a management node identifier argument was passed
        my $management_node_identifier = shift;
+       my $management_node_hostname;
        if ($management_node_identifier) {
                $management_node_hostname = 
$self->data->get_management_node_hostname($management_node_identifier);
                if ($management_node_hostname) {
@@ -912,12 +1087,12 @@ sub get_image_repository_directory_path
                }
        }
        else {
-               $management_node_hostname = $local_management_node_hostname;
+               $management_node_hostname = 
$self->data->get_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};
+       if 
(defined($self->{xcat_image_repository_directory_path}{$image_name}{$management_node_hostname}))
 {
+               return 
$self->{xcat_image_repository_directory_path}{$image_name}{$management_node_hostname};
        }
        
        my $management_node_install_path = 
$self->data->get_management_node_install_path($management_node_identifier);
@@ -942,117 +1117,24 @@ sub get_image_repository_directory_path
                "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;
+       
+       my $image_repository_directory_path;
        if ($os_source_path =~ /^\//) {
-               $image_install_path = $os_source_path;
+               # If image OS source path has a leading /, assume it was meant 
to be absolute
+               $image_repository_directory_path = $os_source_path;
        }
-       else {
-               $image_install_path = 
"$management_node_install_path/$os_source_path";
-       }
-
-       # Note: $XCAT_ROOT has a leading /
-       # Note: $image_install_path has a leading /
-       if ($os_install_type eq 'kickstart') {
-               # Kickstart installs use the xCAT path for both repo and tmpl 
paths
-               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;
+       elsif ($os_install_type eq 'kickstart') {
+               my $nodetype_image_os_name = 
$self->get_nodetype_image_os_name($image_name) || $os_source_path;
+               $image_repository_directory_path = 
"$management_node_install_path/$nodetype_image_os_name/$image_architecture";
        }
        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;
+               # Partimage
+               $image_repository_directory_path = 
"$management_node_install_path/$os_source_path/$image_architecture";
        }
+       
+       
$self->{xcat_image_repository_directory_path}{$image_name}{$management_node_hostname}
 = $image_repository_directory_path;
+       notify($ERRORS{'DEBUG'}, 0, "determined repository directory path: 
$self->{xcat_image_repository_directory_path}{$image_name}{$management_node_hostname}");
+       return 
$self->{xcat_image_repository_directory_path}{$image_name}{$management_node_hostname};
 } ## end sub get_image_repository_directory_path
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -1337,7 +1419,6 @@ sub _edit_nodelist {
        my $image_data = $self->create_datastructure_object({image_identifier 
=> $image_name}) || return;
        my $image_os_install_type = $image_data->get_image_os_install_type() || 
return;
        my $image_project = $image_data->get_image_project() || return;
-       my $image_os_name = $image_data->get_image_os_name() || return;
        
        my $request_state_name = $self->data->get_request_state_name();
        
@@ -1421,11 +1502,19 @@ sub _edit_nodetype {
        
        my $request_state_name = $self->data->get_request_state_name();
        
+       my $nodetype_os;
        if ($request_state_name eq 'image' || $image_os_install_type =~ 
/image/) {
-               $image_os_name = 'image';
+               $nodetype_os = 'image';
+       }
+       elsif ($image_os_install_type =~ /kickstart/i) {
+               # Try to dynamically determine the value for nodetype.os
+               $nodetype_os = $self->get_nodetype_image_os_name($image_name);
+       }
+       else {
+               $nodetype_os = $image_os_name;
        }
        
-       my $command = "$XCAT_ROOT/bin/nodech $computer_node_name 
nodetype.os=$image_os_name nodetype.arch=$image_architecture 
nodetype.profile=$image_name";
+       my $command = "$XCAT_ROOT/bin/nodech $computer_node_name 
nodetype.os=$nodetype_os nodetype.arch=$image_architecture 
nodetype.profile=$image_name";
        my ($exit_status, $output) = $self->mn_os->execute($command);
        if (!defined($output)) {
                notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
edit xCAT configuration of $computer_node_name: $command");


Reply via email to