in managementnode/lib/VCL/Module/OS.pm [5122:5271]
sub mount_nfs_shares {
my $self = shift;
if (ref($self) !~ /VCL::Module/) {
notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
return;
}
my $management_node_id = $self->data->get_management_node_id();
my $computer_name = $self->data->get_computer_short_name();
my $user_uid = $self->data->get_user_uid();
# Get the NFS mount information configured for the management node from the variable table
my $nfsmount_variable_name = "nfsmount|$management_node_id";
my $nfsmount_variable_value = get_variable($nfsmount_variable_name);
if (!$nfsmount_variable_value) {
notify($ERRORS{'DEBUG'}, 0, "'$nfsmount_variable_name' variable is NOT configured for management node $management_node_id");
return 1;
}
notify($ERRORS{'DEBUG'}, 0, "retrieved '$nfsmount_variable_name' variable configured for management node: '$nfsmount_variable_value'");
my $error_encountered = 0;
MOUNT_SPECIFICATION: for my $mount_specification (split(/;/, $nfsmount_variable_value)) {
# Format:
# <IP/hostname>:<remote directory>,<local directory>
# Example:
# 10.0.0.12:/users/home/[username],/home/[username]
my ($remote_host, $remote_specification, $local_specification) = $mount_specification =~
/
^\s*
([^:\s]+) # $remote_host
\s*:\s* # :
(\/[^,]*[^,\s\/])\/? # $remote_specification
\s*,\s* # ,
(\/.*[^\s\/])\/? # $local_specification
\s*$
/gx;
if (!defined($remote_host) || !defined($remote_specification) || !defined($local_specification)) {
notify($ERRORS{'CRITICAL'}, 0, "failed to parse mount specification: '$mount_specification'");
$error_encountered = 1;
next MOUNT_SPECIFICATION;
}
# Replace variables in local and remote directory paths
my $local_substituted = $self->data->substitute_string_variables($local_specification);
my $remote_substituted = $self->data->substitute_string_variables($remote_specification);
my $remote_target = "$remote_host:$remote_substituted";
notify($ERRORS{'DEBUG'}, 0, "parsed mount definition: '$mount_specification'\n" .
"remote storage target : $remote_target" . ($remote_specification ne $remote_substituted ? " (specification: $remote_specification)" : '') . "\n" .
"local mount directory : $local_substituted " . ($local_specification ne $local_substituted ? " (specification: $local_specification)" : '')
);
# Specify ignore error option to prevent warnings on first attempt
my $mount_result = $self->nfs_mount_share($remote_target, $local_substituted, 1);
# If successful or failed and returned undefined, stop processing this share
if (!defined($mount_result)) {
# Unrepairable error encountered
$error_encountered = 1;
next MOUNT_SPECIFICATION;
}
elsif ($mount_result == 1) {
# Successfully mounted share
next MOUNT_SPECIFICATION;
}
# nfs_mount_share() returned 0 indicating the remote directory does not exist
notify($ERRORS{'OK'}, 0, "unable to mount $remote_target on $computer_name on first attempt, checking if directories need to be created");
# Get the last component of the remote directory specification following the last forward slash
my ($remote_directory_name_specification) = $remote_specification =~
/
\/
(
[^
\/
]+
)
$
/gx;
if (!$remote_directory_name_specification) {
notify($ERRORS{'WARNING'}, 0, "failed to mount share on $computer_name: $remote_target --> $local_substituted, no attempt made to create user/reservation-specific directory on share because the remote directory name specification could not be determined: $remote_specification");
return;
}
elsif ($remote_directory_name_specification !~
/
\[
[^
\]
]+
\]
/gx) {
notify($ERRORS{'WARNING'}, 0, "failed to mount share on $computer_name: $remote_target --> $local_substituted, no attempt made to create user/reservation-specific directory on share because the remote directory name specification does not contain a substitution value: $remote_directory_name_specification");
return;
}
# Get the remote directory name and its parent directory path
my ($remote_parent_directory_path, $remote_directory_name) = $remote_substituted =~
/
^
(
\/.+
)
\/
(
[^
\/
]+
)
$
/gx;
if (!defined($remote_directory_name)) {
notify($ERRORS{'WARNING'}, 0, "failed to mount share on $computer_name: $remote_target --> $local_substituted, no attempt made to create user/reservation-specific directory on share because the remote directory name and its parent directory path could not be determined: $remote_substituted");
return;
}
notify($ERRORS{'DEBUG'}, 0, "attempting to create user/reservation-specific directory on share, remote directory name specification contains a substitution value: $remote_directory_name_specification --> $remote_directory_name");
# Attempt to mount the remote parent directory on the management node
my $mn_temp_remote_target = "$remote_host:$remote_parent_directory_path";
my $mn_temp_mount_directory_path = tempdir(CLEANUP => 1);
my $mn_temp_create_directory_path = "$mn_temp_mount_directory_path/$remote_directory_name";
if (!$self->mn_os->nfs_mount_share($mn_temp_remote_target, $mn_temp_mount_directory_path)) {
notify($ERRORS{'WARNING'}, 0, "failed to mount share on $computer_name: $remote_target --> $local_substituted, failed to temporarily mount remote parent directory share on management node: $mn_temp_remote_target --> $mn_temp_mount_directory_path");
return;
}
# Try to create the directory containing the substitution value
if (!$self->mn_os->create_directory($mn_temp_create_directory_path)) {
notify($ERRORS{'WARNING'}, 0, "failed to mount share on $computer_name: $remote_target --> $local_substituted, mounted temporary remote parent directory share on management node ($mn_temp_remote_target) but failed to create '$remote_directory_name' subdirectory under it");
$self->mn_os->nfs_unmount_share($mn_temp_mount_directory_path);
return;
}
# Check if the directory name contains a substitution for user-specific data
if ($remote_directory_name_specification =~ /\[user/) {
$self->mn_os->set_file_owner($mn_temp_create_directory_path, $user_uid);
# Set the permissions on the directory to 700 so other users can't read contents
$self->mn_os->set_file_permissions($mn_temp_create_directory_path, '700');
}
$self->mn_os->nfs_unmount_share($mn_temp_mount_directory_path);
# Try to mount the share on the computer again
$self->nfs_mount_share($remote_target, $local_substituted) || $error_encountered++;
}
return !$error_encountered
}