Author: arkurth
Date: Wed May  6 14:07:44 2015
New Revision: 1677997

URL: http://svn.apache.org/r1677997
Log:
VCL-844
Reworked much of VMware.pm::migrat_vm to overcome issues with VMs which use 
dedicated vmdk files - mainly for server requests.

Added optional type argument to OS.pm::find_files and 
vSphere_SDK.pm::find_files.

Moved recently created SSH key subroutines from OS.pm to Linux.pm. They do not 
work as-is on Windows. Reworked new SSH subroutines in VMware.pm. Most of this 
code has been generalized and now exists in Linux.pm.

Added VMware.pm::add_ssh_host_key_to_known_hosts. SSH/SCP would hang on host to 
host operations without any warning. This should allow host-host communication 
to work without any manual changes.

Added caching to VIM_SSH.pm::_get_vm_id. This subroutine was inefficiently 
being called numerous times for basic operations such as register_vm. The 
cached VM ID is deleted when a VM is unregistered.

Updated vSphere_SDK.pm::initialize to attempt to load VIExt (vSphere SDK) after 
checking if vmprofile username and password are defined. If not defined, 
initialize returns immediately. This prevents unnecessary warnings from 
appearing in vcld.log.

Added code to vSphere_SDK.pm::initialize to attempt to use the result of 
determine_remote_connection_target.

Added vSphere_SDK.pm::get_vm_virtual_disk_file_paths to match VIM_SSH.pm. This 
is now used in VMware.pm::delete_vm. Reworked delete_vm. It was not deleting 
the directory containing the .vmdk for server reservations under some 
circumstances.

Renamed VMware.pm::_get_vmx_file_path_computer_name to 
_get_file_path_computer_name. Updated it to attempt to determine a computer 
name from any path, not just a .vmx file path. This allows a VM's working 
directory path to be passed to it. Updated VMware.pm::is_vmdk_directory_shared 
to call _get_file_path_computer_name as an extra security check.


VCL-853
Updated vSphere_SDK.pm::_get_resource_pool_view to return the root pool if a 
pool isn't configured in the VM profile and multiple pools are found on this 
host.


Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/vSphere_SDK.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1677997&r1=1677996&r2=1677997&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed May  6 14:07:44 2015
@@ -3319,11 +3319,20 @@ sub copy_file_from {
 
 =head2 find_files
 
- Parameters  : $base_directory_path, $file_pattern, $search_subdirectories 
(optional)
+ Parameters  : $base_directory_path, $file_pattern, $search_subdirectories 
(optional), $type (optional)
  Returns     : array
  Description : Finds files under the base directory and any subdirectories path
                matching the file pattern. The search is not case sensitive. An
                array is returned containing matching file paths.
+               
+               Subdirectories will be searched if the $search_subdirectories
+               argument is true or not supplied.
+               
+               If the $type argument is supplied, it must be one of the
+               following:
+                  f - Only search for files (default behavior)
+                  d - Only search for directories
+                  * - Search for files and directories
 
 =cut
 
@@ -3335,7 +3344,7 @@ sub find_files {
        }
        
        # Get the arguments
-       my ($base_directory_path, $file_pattern, $search_subdirectories) = @_;
+       my ($base_directory_path, $file_pattern, $search_subdirectories, $type) 
= @_;
        if (!$base_directory_path || !$file_pattern) {
                notify($ERRORS{'WARNING'}, 0, "base directory path and file 
pattern arguments were not specified");
                return;
@@ -3343,6 +3352,25 @@ sub find_files {
        
        $search_subdirectories = 1 if !defined($search_subdirectories);
        
+       my $type_string;
+       $type = 'f' unless defined $type;
+       if ($type =~ /^f$/i) {
+               $type = 'f';
+               $type_string = 'files';
+       }
+       elsif ($type =~ /^d$/i) {
+               $type = 'd';
+               $type_string = 'directories';
+       }
+       elsif ($type =~ /^\*$/i) {
+               $type = undef;
+               $type_string = 'files and directories';
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unsupported type argument: 
'$type'");
+               return;
+       }
+       
        # Normalize the arguments
        $base_directory_path = normalize_file_path($base_directory_path);
        $file_pattern = normalize_file_path($file_pattern);
@@ -3360,17 +3388,17 @@ sub find_files {
        
        COMMAND: for my $find_command (@find_commands) {
                # Run the find command
-               my $command = "$find_command \"$base_directory_path\" -iname 
\"$file_pattern\" -type f";
+               my $command = "$find_command \"$base_directory_path\" -iname 
\"$file_pattern\"";
+               $command .= " -type $type" if $type;
                
                if (!$search_subdirectories) {
                        $command .= " -maxdepth 1";
                }
                
-               #notify($ERRORS{'DEBUG'}, 0, "attempting to find files on 
$computer_node_name, base directory path: '$base_directory_path', pattern: 
$file_pattern, command: $command");
-               
+               #notify($ERRORS{'DEBUG'}, 0, "attempting to find $type_string 
on $computer_node_name, base directory path: '$base_directory_path', pattern: 
$file_pattern, command: $command");
                my ($exit_status, $output) = $self->execute($command, 0);
                if (!defined($output)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to run command to 
find files on $computer_node_name, base directory path: '$base_directory_path', 
pattern: $file_pattern, command:\n$command");
+                       notify($ERRORS{'WARNING'}, 0, "failed to run command to 
find $type_string on $computer_node_name, base directory path: 
'$base_directory_path', pattern: $file_pattern, command:\n$command");
                        return;
                }
                elsif (grep(/find:.*No such file or directory/i, @$output)) {
@@ -3383,7 +3411,7 @@ sub find_files {
                        next;
                }
                elsif (grep(/find: /i, @$output)) {
-                       notify($ERRORS{'WARNING'}, 0, "error occurred 
attempting to find files on $computer_node_name\nbase directory path: 
$base_directory_path\npattern: $file_pattern\ncommand: $command\noutput:\n" . 
join("\n", @$output));
+                       notify($ERRORS{'WARNING'}, 0, "error occurred 
attempting to find $type_string on $computer_node_name\nbase directory path: 
$base_directory_path\npattern: $file_pattern\ncommand: $command\noutput:\n" . 
join("\n", @$output));
                        return;
                }
                
@@ -3394,8 +3422,8 @@ sub find_files {
                
                my $file_count = scalar(@files);
                
-               notify($ERRORS{'DEBUG'}, 0, "files found under 
$base_directory_path matching '$file_pattern': $file_count");
-               #notify($ERRORS{'DEBUG'}, 0, "files found: $file_count, base 
directory: '$base_directory_path', pattern: '$file_pattern'\ncommand: 
'$command', output:\n" . join("\n", @$output));
+               notify($ERRORS{'DEBUG'}, 0, "$type_string found under 
$base_directory_path matching pattern '$file_pattern': $file_count");
+               #notify($ERRORS{'DEBUG'}, 0, "$type_string found: $file_count, 
base directory: '$base_directory_path', pattern: '$file_pattern'\ncommand: 
'$command', output:\n" . join("\n", @$output));
                return @files;
        }
        
@@ -3450,7 +3478,7 @@ sub get_file_checksum {
 
 =head2 get_tools_file_paths
 
- Parameters  : $pattern
+ Parameters  : $pattern (optional)
  Returns     : boolean
  Description : Scans the tools directory on the management node for any files
                which are intended for the OS of the reservation image. The OS
@@ -4095,182 +4123,6 @@ sub get_cluster_info_file_path {
        return $self->{cluster_info_file_path};
 }
 
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 generate_ssh_key_files
-
- Parameters  : $private_key_file_path, $type (optional), $bits (optional), 
$comment (optional), $passphrase, $options (optional)
- Returns     : boolean
- Description : Calls ssh-keygen to generate an SSH private key file.
-
-=cut
-
-sub generate_ssh_key_files {
-       my $self = shift;
-       if (ref($self) !~ /VCL::Module::OS/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my ($private_key_file_path, $type, $bits, $comment, $passphrase, 
$options) = @_;
-       if (!$private_key_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
-               return;
-       }
-       $type = 'rsa' unless $type;
-       $passphrase = '' unless $passphrase;
-       
-       my $computer_name = $self->data->get_computer_short_name();
-       
-       # Make sure the file does not already exist
-       if ($self->file_exists($private_key_file_path)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH key, file 
already exists on $computer_name: $private_key_file_path");
-               return;
-       }
-       
-       my $command = "ssh-keygen -t $type -f \"$private_key_file_path\" -N 
\"$passphrase\"";
-       $command .= " -b $bits" if defined($bits);
-       $comment .= " $options" if defined($options);
-       
-       if (defined($comment)) {
-               $comment =~ s/\\*(["])/\\"$1/g;
-               $command .= " -C \"$comment\"";;
-       }
-       
-       my ($exit_status, $output) = $self->mn_os->execute($command);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
generate SSH key on $computer_name: $command");
-               return;
-       }
-       elsif ($exit_status ne '0') {
-               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH key on 
$computer_name, exit status: $exit_status, command:\n$command\noutput:\n" . 
join("\n", @$output));
-               return;
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "generated SSH key on $computer_name: 
$private_key_file_path, command: $command");
-               return 1;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 generate_ssh_public_key_string
-
- Parameters  : $private_key_file_path, $comment (optional)
- Returns     : boolean
- Description : Calls ssh-keygen to retrieve the corresponding SSH public key
-               from a private key file.
-
-=cut
-
-sub generate_ssh_public_key_string {
-       my $self = shift;
-       if (ref($self) !~ /VCL::Module::OS/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my ($private_key_file_path, $comment) = @_;
-       if (!$private_key_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
-               return;
-       }
-       
-       my $computer_name = $self->data->get_computer_short_name();
-       
-       # Make sure the private key file exists
-       if (!$self->file_exists($private_key_file_path)) {
-               notify($ERRORS{'WARNING'}, 0, "unable to generate SSH public 
key, private key file does not exist on $computer_name: 
$private_key_file_path");
-               return;
-       }
-       
-       my $command = "ssh-keygen -y -f \"$private_key_file_path\"";
-       my ($exit_status, $output) = $self->mn_os->execute($command);
-       if (!defined($output)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
generate SSH public key string from $private_key_file_path on $computer_name");
-               return;
-       }
-       elsif ($exit_status ne '0') {
-               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH public 
key string from $private_key_file_path on $computer_name, exit status: 
$exit_status, command:\n$command\noutput:\n" . join("\n", @$output));
-               return;
-       }
-       
-       my ($ssh_public_key_string) = grep(/^ssh-.*/, @$output);
-       if ($ssh_public_key_string) {
-               if ($comment) {
-                       if ($ssh_public_key_string !~ /=/) {
-                               $ssh_public_key_string .= "==";
-                       }
-                       $ssh_public_key_string .= " $comment";
-               }
-               notify($ERRORS{'OK'}, 0, "generated SSH public key string from 
$private_key_file_path on $computer_name: $ssh_public_key_string");
-               return $ssh_public_key_string;
-       }
-       else {
-               notify($ERRORS{'OK'}, 0, "failed to generate SSH public key 
string from $private_key_file_path on $computer_name, output does not contain a 
line beginning with 'ssh-', command:\n$command\noutput:\n" . join("\n", 
@$output));
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 create_ssh_public_key_file
-
- Parameters  : $private_key_file_path, $public_key_file_path, $comment 
(optional)
- Returns     : boolean
- Description : Calls ssh-keygen to retrieve the corresponding SSH public key
-               from a private key file and generates a file containing the
-               public key.
-
-=cut
-
-sub create_ssh_public_key_file {
-       my $self = shift;
-       if (ref($self) !~ /VCL::Module::OS/i) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my ($private_key_file_path, $public_key_file_path, $comment) = @_;
-       if (!$private_key_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
-               return;
-       }
-       if (!$public_key_file_path) {
-               notify($ERRORS{'WARNING'}, 0, "public key file path argument 
was not specified");
-               return;
-       }
-       
-       my $computer_name = $self->data->get_computer_short_name();
-       
-       # Make sure the private key file exists
-       if (!$self->file_exists($private_key_file_path)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH public 
key file, private key file does not exist on $computer_name: 
$private_key_file_path");
-               return;
-       }
-       
-       # Make sure the public key file does not exist
-       if ($self->file_exists($public_key_file_path)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to create SSH public key 
file, public key file already exists on $computer_name: $public_key_file_path");
-               return;
-       }
-       
-       my $public_key_string = 
$self->generate_ssh_public_key_string($private_key_file_path, $comment);
-       if (!$public_key_string) {
-               notify($ERRORS{'WARNING'}, 0, "failed to create SSH public key 
file: $public_key_file_path, public key string could not be retrieved from 
private key file: $private_key_file_path");
-               return;
-       }
-       
-       if ($self->create_text_file($public_key_file_path, $public_key_string)) 
{
-               notify($ERRORS{'DEBUG'}, 0, "created SSH public key file: 
$public_key_file_path");
-               return 1;
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to create SSH public key 
file: $public_key_file_path");
-               return;
-       }
-}
-
 #///////////////////////////////////////////////////////////////////////////
 
 1;

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1677997&r1=1677996&r2=1677997&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed May  6 14:07:44 2015
@@ -57,6 +57,7 @@ use VCL::utils;
 use English qw( -no_match_vars );
 use Net::Netmask;
 use File::Basename;
+use File::Temp qw( tempfile mktemp );
 
 ##############################################################################
 
@@ -5174,7 +5175,8 @@ sub command_exists {
        
        my $computer_node_name = $self->data->get_computer_node_name();
        
-       my ($exit_status, $output) = $self->execute("which $shell_command", 0);
+       my $command = "which $shell_command";
+       my ($exit_status, $output) = $self->execute($command, 0);
        if (!defined($output)) {
                notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if the '$shell_command' shell command exists on $computer_node_name");
                return;
@@ -5185,7 +5187,7 @@ sub command_exists {
                return 1;
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "'$shell_command' command does NOT 
exist on $computer_node_name");
+               notify($ERRORS{'DEBUG'}, 0, "'$shell_command' command does NOT 
exist on $computer_node_name, command: $command\noutput:\n" . join("\n", 
@$output));
                $self->{command_exists}{$shell_command} = 0;
                return 0;
        }
@@ -5853,6 +5855,324 @@ sub is_display_manager_running {
        }
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 generate_ssh_private_key_file
+
+ Parameters  : $private_key_file_path, $type (optional), $bits (optional), 
$comment (optional), $passphrase, $options (optional)
+ Returns     : boolean
+ Description : Calls ssh-keygen or dropbearkey to generate an SSH private key
+               file.
+
+=cut
+
+sub generate_ssh_private_key_file {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module::OS/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($private_key_file_path, $type, $bits, $comment, $passphrase, 
$options) = @_;
+       if (!$private_key_file_path) {
+               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
+               return;
+       }
+       $type = 'rsa' unless $type;
+       $passphrase = '' unless $passphrase;
+       
+       if (defined($comment)) {
+               $comment =~ s/\\*(["])/\\"$1/g;
+       }
+       
+       my $computer_name = $self->data->get_computer_short_name();
+       
+       # Make sure the file does not already exist
+       if ($self->file_exists($private_key_file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH key, file 
already exists on $computer_name: $private_key_file_path");
+               return;
+       }
+       
+       if ($self->command_exists('ssh-keygen')) {
+               if 
($self->_generate_ssh_private_key_file_helper($private_key_file_path, $type, 
$bits, $comment, $passphrase, $options, 'ssh-keygen')) {
+                       return 1;
+               }
+       }
+       if ($self->command_exists('dropbearkey')) {
+               if 
($self->_generate_ssh_private_key_file_helper($private_key_file_path, $type, 
$bits, $comment, $passphrase, $options, 'dropbearkey')) {
+                       return 1;
+               }
+       }
+       
+       if (ref($self) =~ /ManagementNode/) {
+               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH key on 
$computer_name: $private_key_file_path");
+               return;
+       }
+       
+       my $mn_temp_file_path = mktemp($computer_name . 'XXXXXX');
+       notify($ERRORS{'DEBUG'}, 0, "attempting to create SSH private key file 
on this management node ($mn_temp_file_path) and copy it to $computer_name 
($private_key_file_path)");
+       my $result = 
$self->mn_os->generate_ssh_private_key_file($mn_temp_file_path, $type, $bits, 
$comment, $passphrase, $options);
+       if (!$result) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create SSH private key 
file on this management node and copy it to $private_key_file_path on 
$computer_name");
+               $self->mn_os->delete_file($mn_temp_file_path);
+               return;
+       }
+       
+       if (!$self->copy_file_to($mn_temp_file_path, $private_key_file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "create SSH private key file on 
this management node but failed to copy it to $private_key_file_path on 
$computer_name");
+               $self->mn_os->delete_file($mn_temp_file_path);
+               return;
+       }
+       else {
+               $self->mn_os->delete_file($mn_temp_file_path);
+               notify($ERRORS{'OK'}, 0, "created SSH private key file on this 
management and copied it to $private_key_file_path on $computer_name");
+               return 1;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _generate_ssh_private_key_file_helper
+
+ Parameters  : $private_key_file_path, $type, $bits, $comment, $passphrase, 
$options, $utility
+ Returns     : boolean
+ Description : Calls ssh-keygen to generate an SSH private key file.
+
+=cut
+
+sub _generate_ssh_private_key_file_helper {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module::OS/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($private_key_file_path, $type, $bits, $comment, $passphrase, 
$options, $utility) = @_;
+       if (!defined($utility)) {
+               notify($ERRORS{'WARNING'}, 0, "utility argument was not 
supplied");
+               return;
+       }
+       
+       my $computer_name = $self->data->get_computer_short_name();
+       
+       my $command;
+       if ($utility eq 'ssh-keygen') {
+               $command = "ssh-keygen -t $type -f \"$private_key_file_path\" 
-N \"$passphrase\"";
+               $command .= " -b $bits" if (defined($bits) && length($bits));
+               $comment .= " $options" if (defined($options) && 
length($options));
+               $command .= " -C \"$comment\"" if (defined($comment) && 
length($comment));
+       }
+       elsif ($utility eq 'dropbearkey') {
+               $command = "dropbearkey -t $type -f \"$private_key_file_path\"";
+               $command .= " -s $bits" if (defined($bits) && length($bits));
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "invalid utility argument 
provided: '$utility', it must either be 'ssh-keygen' or 'dropbearkey'");
+               return;
+       }
+       
+       my ($exit_status, $output) = $self->execute($command);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
generate SSH key using $utility on $computer_name: $command");
+               return;
+       }
+       elsif ($exit_status ne '0') {
+               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH key using 
$utility on $computer_name, exit status: $exit_status, 
command:\n$command\noutput:\n" . join("\n", @$output));
+               return;
+       }
+       else {
+               notify($ERRORS{'OK'}, 0, "generated SSH key using $utility on 
$computer_name: $private_key_file_path, command: $command");
+               return 1;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 generate_ssh_public_key_file
+
+ Parameters  : $private_key_file_path, $public_key_file_path, $comment 
(optional)
+ Returns     : boolean
+ Description : Calls ssh-keygen to retrieve the corresponding SSH public key
+               from a private key file and generates a file containing the
+               public key.
+
+=cut
+
+sub generate_ssh_public_key_file {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module::OS/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($private_key_file_path, $public_key_file_path, $comment) = @_;
+       if (!$private_key_file_path) {
+               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
+               return;
+       }
+       if (!$public_key_file_path) {
+               notify($ERRORS{'WARNING'}, 0, "public key file path argument 
was not specified");
+               return;
+       }
+       
+       my $computer_name = $self->data->get_computer_short_name();
+       
+       # Make sure the private key file exists
+       if (!$self->file_exists($private_key_file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to generate SSH public 
key file, private key file does not exist on $computer_name: 
$private_key_file_path");
+               return;
+       }
+       
+       # Make sure the public key file does not exist
+       if ($self->file_exists($public_key_file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create SSH public key 
file, public key file already exists on $computer_name: $public_key_file_path");
+               return;
+       }
+       
+       my $public_key_string = 
$self->get_ssh_public_key_string($private_key_file_path, $comment);
+       if (!$public_key_string) {
+               notify($ERRORS{'WARNING'}, 0, "failed to create SSH public key 
file: $public_key_file_path, public key string could not be retrieved from 
private key file: $private_key_file_path");
+               return;
+       }
+       
+       if ($self->create_text_file($public_key_file_path, $public_key_string)) 
{
+               notify($ERRORS{'DEBUG'}, 0, "created SSH public key file: 
$public_key_file_path");
+               return 1;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to create SSH public key 
file: $public_key_file_path");
+               return;
+       }
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_ssh_public_key_string
+
+ Parameters  : $private_key_file_path, $comment (optional)
+ Returns     : boolean
+ Description : Extracts the SSH public key from a private key file.
+
+=cut
+
+sub get_ssh_public_key_string {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module::OS/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($private_key_file_path, $comment) = @_;
+       if (!$private_key_file_path) {
+               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
+               return;
+       }
+       
+       my $computer_name = $self->data->get_computer_short_name();
+       
+       # Make sure the private key file exists
+       if (!$self->file_exists($private_key_file_path)) {
+               notify($ERRORS{'WARNING'}, 0, "unable to retrieve SSH public 
key, private key file does not exist on $computer_name: 
$private_key_file_path");
+               return;
+       }
+       
+       my $public_key_string;
+       if ($self->command_exists('ssh-keygen')) {
+               $public_key_string = 
$self->_get_ssh_public_key_string_helper($private_key_file_path, 'ssh-keygen');
+       }
+       if (!$public_key_string && $self->command_exists('dropbearkey')) {
+               $public_key_string = 
$self->_get_ssh_public_key_string_helper($private_key_file_path, 'dropbearkey');
+       }
+       if ($public_key_string) {
+               if ($comment) {
+                       $public_key_string =~ s/(ssh-[^\s]+\s[^\s=]+).*$/$1== 
$comment/g;
+               }
+               return $public_key_string;
+       }
+       
+       if (ref($self) =~ /ManagementNode/) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve SSH public 
key from private key file on $computer_name: $private_key_file_path");
+               return;
+       }
+       else {
+               notify($ERRORS{'DEBUG'}, 0, "attempting to copy SSH private key 
file $private_key_file_path from $computer_name and extract the public key on 
this management node");
+       }
+       
+       my ($mn_temp_file_handle, $mn_temp_file_path) = tempfile(SUFFIX => 
'.key', UNLINK => 1);
+       if (!$self->copy_file_from($private_key_file_path, $mn_temp_file_path)) 
{
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve SSH public 
key from private key file on $computer_name: $private_key_file_path, failed to 
copy temp file to management node");
+               $self->mn_os->delete_file($mn_temp_file_path);
+               return;
+       }
+       $self->mn_os->set_file_permissions($mn_temp_file_path, '0400');
+       
+       $public_key_string = 
$self->mn_os->get_ssh_public_key_string($mn_temp_file_path, $comment);
+       $self->mn_os->delete_file($mn_temp_file_path);
+       return $public_key_string;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 _get_ssh_public_key_string_helper
+
+ Parameters  : $private_key_file_path, $utility
+ Returns     : boolean
+ Description : 
+
+=cut
+
+sub _get_ssh_public_key_string_helper {
+       my $self = shift;
+       if (ref($self) !~ /VCL::Module::OS/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($private_key_file_path, $utility) = @_;
+       if (!$private_key_file_path) {
+               notify($ERRORS{'WARNING'}, 0, "private key file path argument 
was not specified");
+               return;
+       }
+       elsif (!$utility) {
+               notify($ERRORS{'WARNING'}, 0, "utility argument (ssh-keygen or 
dropbearkey) was not specified");
+               return;
+       }
+       
+       my $computer_name = $self->data->get_computer_short_name();
+       
+       my $command;
+       if ($utility eq 'ssh-keygen') {
+               $command = "ssh-keygen -y -f \"$private_key_file_path\"";
+       }
+       elsif ($utility eq 'dropbearkey') {
+               $command = "/bin/dropbearkey -f \"$private_key_file_path\" -y";
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "invalid utility argument 
provided: '$utility', it must either be 'ssh-keygen' or 'dropbearkey'");
+               return;
+       }
+       
+       my ($exit_status, $output) = $self->execute($command);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
retrieve SSH public key string using $utility from $private_key_file_path on 
$computer_name");
+               return;
+       }
+       elsif ($exit_status ne 0) {
+               notify($ERRORS{'WARNING'}, 0, "failed to retrieve SSH public 
key string using $utility from $private_key_file_path on $computer_name, exit 
status: $exit_status, command:\n$command\noutput:\n" . join("\n", @$output));
+               return;
+       }
+       
+       my ($ssh_public_key_string) = grep(/^ssh-.*/, @$output);
+       if ($ssh_public_key_string) {
+               notify($ERRORS{'OK'}, 0, "retrieved SSH public key string using 
$utility from $private_key_file_path on 
$computer_name:\n$ssh_public_key_string");
+               return $ssh_public_key_string;
+       }
+       else {
+               notify($ERRORS{'OK'}, 0, "failed to retrieved SSH public key 
string using $utility from $private_key_file_path on $computer_name, output 
does not contain a line beginning with 'ssh-', command:\n$command\noutput:\n" . 
join("\n", @$output));
+               return;
+       }
+}
+
 ##/////////////////////////////////////////////////////////////////////////////
 1;
 __END__

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm?rev=1677997&r1=1677996&r2=1677997&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VIM_SSH.pm Wed 
May  6 14:07:44 2015
@@ -532,6 +532,8 @@ sub _get_vm_id {
                return;
        }
        
+       return $self->{vm_id}{$vmx_file_path} if $self->{vm_id}{$vmx_file_path};
+       
        # Get the VM IDs and vmx paths
        my $vm_list = $self->_get_vm_list();
        if (!defined($vm_list)) {
@@ -540,7 +542,10 @@ sub _get_vm_id {
        }
        
        for my $vm_id (keys %$vm_list) {
-               return $vm_id if ($vm_list->{$vm_id} && $vmx_file_path eq 
$vm_list->{$vm_id});
+               if ($vm_list->{$vm_id} && $vmx_file_path eq $vm_list->{$vm_id}) 
{
+                       $self->{vm_id}{$vmx_file_path} = $vm_id;
+                       return $vm_id;
+               }
        }
        
        notify($ERRORS{'WARNING'}, 0, "unable to determine VM ID, vmx file is 
not registered: $vmx_file_path, registered VMs:\n" . format_data($vm_list));
@@ -1484,6 +1489,10 @@ sub vm_unregister {
        
        my $vim_cmd_arguments = "vmsvc/unregister $vm_id";
        my ($exit_status, $output) = $self->_run_vim_cmd($vim_cmd_arguments);
+       
+       # Delete cached .vmx - VM ID mapping if previously retrieved
+       delete $self->{vm_id}{$vmx_file_path};
+       
        return if !$output;
        
        # Expected output if the VM is not registered:
@@ -2845,7 +2854,7 @@ sub _get_vm_virtual_disk_file_layout {
        
        my $virtual_disk_file_layout = $self->_parse_vim_cmd_output($output);
        if ($virtual_disk_file_layout) {
-               notify($ERRORS{'DEBUG'}, 0, "retrieved virtual disk file layout 
for VM $vm_id ($vmx_file_path)\n" . format_data($virtual_disk_file_layout));
+               #notify($ERRORS{'DEBUG'}, 0, "retrieved virtual disk file 
layout for VM $vm_id ($vmx_file_path)\n" . 
format_data($virtual_disk_file_layout));
                return $virtual_disk_file_layout;
        }
        else {
@@ -2859,7 +2868,7 @@ sub _get_vm_virtual_disk_file_layout {
 =head2 get_vm_virtual_disk_file_paths
 
  Parameters  : $vmx_file_path
- Returns     : array reference
+ Returns     : array
  Description : Retrieves a VM's virtual disk file layout and returns an array
                reference. Each top-level array element represent entire virtual
                disk and contains an array reference containing the virtual


Reply via email to