Author: arkurth
Date: Wed Oct  5 18:22:54 2011
New Revision: 1179363

URL: http://svn.apache.org/viewvc?rev=1179363&view=rev
Log:
VCL-30
Updated SQL query utils.pm::get_connect_methods subroutine in utils.pm and 
renamed it to get_connect_method_info to match other subroutines. Updated 
OS.pm::process_connect_methods to handle the results returned by 
get_connect_method_info.

Updated Linux.pm::enable_firewall_port to accept the same arguments and scope 
format as Windows.pm::enable_firewall_port.

VCL-503
Added OS.pm::execute_new. This isn't currently called by anything and will 
eventually replace OS.pm::execute. It uses Net::SSH::Expect to keep an SSH 
connection open and then commands are issued to this connection. This speeds 
things up. There are commented out "return...execute_new" lines at the 
beginning of OS.pm::execute and in utils.pm::run_ssh_command. Uncommenting 
these lines will cause the new subroutine to be used.

Other
Added OS type information to the hash returned by get_image_info.  Added 
OS.pm::get_management_node_identity_key_paths subroutine so that the 
comma-separated value is parsed consistently.

Modified:
    incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    incubator/vcl/trunk/managementnode/lib/VCL/utils.pm

Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1179363&r1=1179362&r2=1179363&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Wed Oct  5 
18:22:54 2011
@@ -2319,6 +2319,28 @@ sub get_management_node_public_dns_serve
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_management_node_identity_key_paths
+
+ Parameters  : None
+ Returns     : If successful: array containing paths to SSH identity keys
+               If failed: false
+ Description : Returns an array containing the paths to SSH identity keys
+               configured for the management node.
+
+=cut
+
+sub get_management_node_identity_key_paths {
+       my $keys_string = $ENV{management_node_info}{keys};
+       if (!$keys_string) {
+               notify($ERRORS{'WARNING'}, 0, "no identity key paths are 
configured for the management node");
+               return ();
+       }
+       
+       return split(/\s*[,;]\s*/, $keys_string);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_computer_state_name
 
  Parameters  : computer name (optional

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1179363&r1=1179362&r2=1179363&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm Wed Oct  5 18:22:54 
2011
@@ -52,6 +52,8 @@ use strict;
 use warnings;
 use diagnostics;
 use English '-no_match_vars';
+use Net::SSH::Expect;
+
 use VCL::utils;
 
 ##############################################################################
@@ -547,7 +549,7 @@ sub wait_for_response {
        my $end_time = time();
        my $duration = ($end_time - $start_time);
        
-       #insertloadlog($reservation_id, $computer_id, "osrespond", 
"$computer_node_name is responding to SSH after $duration seconds");
+       # insertloadlog($reservation_id, $computer_id, "osrespond", 
"$computer_node_name is responding to SSH after $duration seconds");
        notify($ERRORS{'OK'}, 0, "$computer_node_name is responding to SSH 
after $duration seconds");
        return 1;
 }
@@ -1577,6 +1579,7 @@ sub create_text_file {
 =cut
 
 sub execute {
+#return execute_new(@_);
        my $self = shift;
        unless (ref($self) && $self->isa('VCL::Module')) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called 
as an object method");
@@ -1615,6 +1618,177 @@ sub execute {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 execute_new
+
+ Parameters  : $computer_name (conditional), $command, $display_output, 
$timeout_seconds, $max_attempts, $port, $user, $password
+ Returns     : array ($exit_status, $output)
+ Description : Executes a command on the computer via SSH.
+
+=cut
+
+sub execute_new {
+       my $argument = shift;
+       my ($computer_name, $command, $display_output, $timeout_seconds, 
$max_attempts, $port, $user, $password);
+       
+       if (!ref($argument) || $argument->isa('VCL::Module')) {
+               if ($argument->isa('VCL::Module')) {
+                       $computer_name = 
$argument->data->get_computer_node_name();
+               }
+               else {
+                       $computer_name = $argument;
+               }
+               ($command, $display_output, $timeout_seconds, $max_attempts, 
$port, $user, $password) = @_;
+       }
+       else {
+               $computer_name = $argument->{node};
+               $command = $argument->{command};
+               $display_output = $argument->{display_output};
+               $timeout_seconds = $argument->{timeout};
+               $max_attempts = $argument->{max_attempts};
+               $port = $argument->{port};
+               $user = $argument->{user};
+               $password = $argument->{password};
+       }
+       
+       if (!$computer_name) {
+               notify($ERRORS{'WARNING'}, 0, "computer name could not be 
determined");
+               return;
+       }
+       if (!$command) {
+               notify($ERRORS{'WARNING'}, 0, "command argument was not 
specified");
+               return;
+       }
+       
+       $display_output = 0 unless $display_output;
+       $timeout_seconds = 60 unless $timeout_seconds;
+       $max_attempts = 1 unless $max_attempts;
+       $port = 22 unless $port;
+       $user = 'root' unless $user;
+       
+       # Override the die handler
+       local $SIG{__DIE__} = sub{};
+       
+       my $ssh;
+       my $attempt = 0;
+       my $attempt_delay = 5;
+       my $attempt_string = '';
+       
+       ATTEMPT: while ($attempt < $max_attempts) {
+               if ($attempt > 0) {
+                       $attempt_string = "attempt $attempt/$max_attempts: ";
+                       $ssh->close() if $ssh;
+                       
+                       notify($ERRORS{'DEBUG'}, 0, $attempt_string . "sleeping 
for $attempt_delay seconds before making next attempt");
+                       sleep $attempt_delay;
+               }
+               
+               $attempt++;
+               $attempt_string = "attempt $attempt/$max_attempts: " if 
($attempt > 1);
+               
+               
+               if (!$ENV{net_ssh_expect}{$computer_name}) {
+                       eval {
+                               $ssh = Net::SSH::Expect->new(
+                                       host => $computer_name,
+                                       user => $user,
+                                       port => $port,
+                                       raw_pty => 1,
+                                       no_terminal => 1,
+                                       ssh_option => '-o 
StrictHostKeyChecking=no',
+                                       timeout => 3,
+                               );
+                               
+                               if ($ssh) {
+                                       notify($ERRORS{'DEBUG'}, 0, "created " 
. ref($ssh) . " object to control $computer_name");
+                               }
+                               else {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to create Net::SSH::Expect object to control $computer_name, $!");
+                                       next ATTEMPT;
+                               }
+                               
+                               if ($ssh->run_ssh()) {
+                                       notify($ERRORS{'DEBUG'}, 0, ref($ssh) . 
" object forked SSH process to control $computer_name");
+                               }
+                               else {
+                                       notify($ERRORS{'WARNING'}, 0, ref($ssh) 
. " object failed to fork SSH process to control $computer_name, $!");
+                                       next ATTEMPT;
+                               }
+                               
+                               #$ssh->exec("stty -echo");
+                               #$ssh->exec("stty raw -echo");
+                               
+                               # Set the timeout counter behaviour:
+                               # If true, sets the timeout to "inactivity 
timeout"
+                               # If false sets it to "absolute timeout"
+                               #$ssh->restart_timeout_upon_receive(1);
+                       };
+                       if ($EVAL_ERROR) {
+                               if ($EVAL_ERROR =~ /^(\w+) at \//) {
+                                       notify($ERRORS{'DEBUG'}, 0, 
$attempt_string . "$1 error occurred initializing Net::SSH::Expect object for 
$computer_name");
+                               }
+                               else {
+                                       notify($ERRORS{'DEBUG'}, 0, 
$attempt_string . "error occurred initializing Net::SSH::Expect object for 
$computer_name");
+                               }
+                               next ATTEMPT;
+                       }
+               }
+               else {
+                       $ssh = $ENV{net_ssh_expect}{$computer_name};
+                       
+                       # Delete the stored SSH object to make sure it isn't 
saved if the command fails
+                       # The SSH object will be added back to %ENV if the 
command completes successfully
+                       delete $ENV{net_ssh_expect}{$computer_name};
+               }
+               
+               notify($ERRORS{'DEBUG'}, 0, $attempt_string . "executing 
command on $computer_name: '$command', timeout: $timeout_seconds seconds") if 
($display_output);
+               $ssh->send($command . ' 2>&1 ; echo exitstatus:$?');
+               
+               my $ssh_wait_status;
+               eval {
+                       $ssh_wait_status = $ssh->waitfor('exitstatus:[0-9]+', 
$timeout_seconds);
+               };
+               
+               if ($EVAL_ERROR) {
+                       if ($EVAL_ERROR =~ /^(\w+) at \//) {
+                               notify($ERRORS{'DEBUG'}, 0, $attempt_string . 
"$1 error occurred executing command on $computer_name: '$command'");
+                       }
+                       else {
+                               notify($ERRORS{'DEBUG'}, 0, $attempt_string . 
"error occurred executing command on $computer_name: '$command'\nerror: 
$EVAL_ERROR");
+                       }
+                       next ATTEMPT;
+               }
+               elsif (!$ssh_wait_status) {
+                       notify($ERRORS{'DEBUG'}, 0, $attempt_string . "command 
timed out after $timeout_seconds seconds on $computer_name: '$command'");
+                       next ATTEMPT;
+               }
+               
+               my $output = $ssh->before() || '';
+               $output =~ s/(^\s+)|(\s+$)//g;
+               
+               my $exit_status_string = $ssh->match() || '';
+               my ($exit_status) = $exit_status_string =~ /(\d)+/;
+               if (!$exit_status_string || !defined($exit_status)) {
+                       my $all_output = $ssh->read_all() || '';
+                       notify($ERRORS{'WARNING'}, 0, $attempt_string . "failed 
to determine exit status from string: '$exit_status_string', 
output:\n$all_output");
+                       next ATTEMPT;
+               }
+               
+               my @output_lines = split(/[\r\n]+/, $output);
+               
+               notify($ERRORS{'OK'}, 0, "executed command on $computer_name: 
'$command', exit status: $exit_status, output:\n$output") if ($display_output);
+               
+               # Save the SSH object for later use
+               $ENV{net_ssh_expect}{$computer_name} = $ssh;
+               
+               return ($exit_status, \@output_lines);
+       }
+       
+       notify($ERRORS{'WARNING'}, 0, $attempt_string . "failed to execute 
command on $computer_name: '$command'") if ($display_output);
+       return;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_os_type
 
  Parameters  : None
@@ -1661,43 +1835,51 @@ sub get_os_type {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 manage_server_access
+
+ Parameters  : None
+ Returns     : 
+ Description : 
+
+=cut
+
 sub manage_server_access {
 
        my $self = shift;
-        if (ref($self) !~ /VCL::Module/i) {
-                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-                return;
-        }
-
-        my $computer_node_name = $self->data->get_computer_node_name() || 
return;
-       my $reservation_id        = $self->data->get_reservation_id();
-       my $server_request_id     = $self->data->get_server_request_id();
-        my $server_request_admingroupid = 
$self->data->get_server_request_admingroupid();
-        my $server_request_logingroupid = 
$self->data->get_server_request_logingroupid();
-
-       #Build list of users.
-       #If in admin group set admin flag
-       #If in both login and admin group, only use admin setting
-       #Check if user is in reserverationaccounts table, add user if needed
-       #Check if user exists on server, add if needed
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+
+       my $computer_node_name          = $self->data->get_computer_node_name() 
|| return;
+       my $reservation_id              = $self->data->get_reservation_id();
+       my $server_request_id           = $self->data->get_server_request_id();
+       my $server_request_admingroupid = 
$self->data->get_server_request_admingroupid();
+       my $server_request_logingroupid = 
$self->data->get_server_request_logingroupid();
+
+       # Build list of users.
+       # If in admin group set admin flag
+       # If in both login and admin group, only use admin setting
+       # Check if user is in reserverationaccounts table, add user if needed
+       # Check if user exists on server, add if needed
        
        my @userlist_admin;
        my @userlist_login;
        my %user_hash;
        my $ssh_allow_list;
 
-       if ( $server_request_admingroupid ) {
+       if ($server_request_admingroupid) {
                @userlist_admin = 
getusergroupmembers($server_request_admingroupid);
        }
-       if ( $server_request_logingroupid ) {
+       if ($server_request_logingroupid) {
                @userlist_login = 
getusergroupmembers($server_request_logingroupid);
        }       
        
        notify($ERRORS{'OK'}, 0, " admin list= @userlist_admin");
        notify($ERRORS{'OK'}, 0, " login list= @userlist_login");
-
        
-       if ( scalar @userlist_admin > 0 ) {
+       
+       if (scalar @userlist_admin > 0) {
                foreach my $str (@userlist_admin) {
                        my ($username,$uid,$vcl_user_id) = split(/:/, $str);
                        $user_hash{$uid}{"username"} = $username;
@@ -1707,7 +1889,7 @@ sub manage_server_access {
                        notify($ERRORS{'OK'}, 0, "adding admin $uid for 
$username ");
                }
        }               
-       if ( scalar @userlist_login > 0 ) {
+       if (scalar @userlist_login > 0) {
                foreach my $str (@userlist_login) {
                        notify($ERRORS{'OK'}, 0, "admin str= $str");
                        my ($username, $uid,$vcl_user_id) = split(/:/, $str);
@@ -1724,18 +1906,18 @@ sub manage_server_access {
                }
        }       
 
-       #Collect users in reservationaccounts table
+       # Collect users in reservationaccounts table
        my %res_accounts = get_reservation_accounts($reservation_id);
        my $not_standalone_list = "";
        my $standalone = 0;
        if(defined($ENV{management_node_info}{NOT_STANDALONE}) && 
$ENV{management_node_info}{NOT_STANDALONE}){
-                $not_standalone_list = 
$ENV{management_node_info}{NOT_STANDALONE};
-        }
+               $not_standalone_list = 
$ENV{management_node_info}{NOT_STANDALONE};
+       }
 
        foreach my $userid (sort keys %user_hash) {
                next if (!($userid));
                if(!exists($res_accounts{$userid})){
-                       #check affiliation
+                       # check affiliation
                        notify($ERRORS{'OK'}, 0, "checking affiliation for 
$userid");
                        my $affiliation_name = 
get_user_affiliation($user_hash{$userid}{vcl_user_id}); 
                        if(defined($affiliation_name)) {
@@ -1744,7 +1926,7 @@ sub manage_server_access {
                                        $standalone = 1;
                                }
                        }
-                       #IF standalone - generate password
+                       # IF standalone - generate password
                        if($standalone) {
                                $user_hash{$userid}{"passwd"} = getpw();
                        }
@@ -1792,10 +1974,9 @@ sub manage_server_access {
 
 =head2 process_connect_methods
 
- Parameters  : None
- Returns     : If successful: 1
-               If failed: 0
- Description : starts and open port for available connection methods
+ Parameters  : none
+ Returns     : boolean
+ Description : Processes the connect methods configured for the image revision.
 
 =cut
 
@@ -1806,84 +1987,111 @@ sub process_connect_methods {
                return;
        }
        
-       my $mode = shift;
-       if (!$mode) {
-               notify($ERRORS{'OK'}, 0, "Mode variable not passed in as an 
argument");
-               return 0;
-       }
-       
-       my $computer_node_name   = $self->data->get_computer_node_name();
-       my $connect_methods      = $self->data->get_connect_methods();
+       my $computer_node_name = $self->data->get_computer_node_name();
+       my $imagerevision_id   = $self->data->get_imagerevision_id();
        
-       foreach my $CMid (sort keys %{$connect_methods} ) {
-               notify($ERRORS{'OK'}, 0, "id= $$connect_methods{$CMid}{id}") 
if(defined ($$connect_methods{$CMid}{id}) );
-               notify($ERRORS{'OK'}, 0, "description= 
$$connect_methods{$CMid}{description}") if(defined 
($$connect_methods{$CMid}{description}) );
-               notify($ERRORS{'OK'}, 0, "port== 
$$connect_methods{$CMid}{port}") if(defined ($$connect_methods{$CMid}{port}) );
-               notify($ERRORS{'OK'}, 0, "servicename= 
$$connect_methods{$CMid}{servicename}") if(defined 
($$connect_methods{$CMid}{servicename}) );
-               notify($ERRORS{'OK'}, 0, "startupscript= 
$$connect_methods{$CMid}{startupscript}") if(defined 
($$connect_methods{$CMid}{startupscript}) );
-               notify($ERRORS{'OK'}, 0, "autoprov= 
$$connect_methods{$CMid}{autoprovisioned}") if(defined 
($$connect_methods{$CMid}{autoprovisioned}) );
-               my $description = $$connect_methods{$CMid}{description};
-               my $port = $$connect_methods{$CMid}{port};
-               
-               my $service_started = 0;        
-               notify($ERRORS{'OK'}, 0, "checking if servicename exists ");
-               if( defined ($$connect_methods{$CMid}{servicename}) && 
$$connect_methods{$CMid}{servicename} ) {
-                       # does service exist
-                       my $servicename = $$connect_methods{$CMid}{servicename};
-                       notify($ERRORS{'OK'}, 0, "trying to start servicename 
$servicename ");
-                       if( $self->can("service_exists")) {
-                               if($self->service_exists($servicename)) {
-                                       if( $self->can("start_service")) {
-                                               if( 
$self->start_service($servicename) ) {
-                                                       notify($ERRORS{'OK'}, 
0, "Service $servicename started");
-                                                       $service_started = 1;
-                                               }
-                                               else {
-                                                       
notify($ERRORS{'WARNING'}, 0, "Service $servicename failed to start");
-                                               }
+       # Retrieve the connect method info hash
+       my $connect_method_info = get_connect_method_info($imagerevision_id);
+       if (!$connect_method_info) {
+               notify($ERRORS{'WARNING'}, 0, "no connect methods are 
configured for image revision $imagerevision_id");
+       }
+       
+       my $remote_ip = $self->data->get_reservation_remote_ip();
+       if (!$remote_ip) {
+               notify($ERRORS{'WARNING'}, 0, "reservation remote IP address is 
not defined, connect methods will be available from any IP address");
+               $remote_ip = '0.0.0.0/0.0.0.0';
+       }
+       
+       CONNECT_METHOD: for my $connect_method_id (sort keys 
%{$connect_method_info} ) {
+               notify($ERRORS{'DEBUG'}, 0, "processing connect method:\n" . 
format_data($connect_method_info->{$connect_method_id}));
+               
+               my $name            = 
$connect_method_info->{$connect_method_id}{name};
+               my $description     = 
$connect_method_info->{$connect_method_id}{description};
+               my $protocol        = 
$connect_method_info->{$connect_method_id}{protocol} || 'TCP';
+               my $port            = 
$connect_method_info->{$connect_method_id}{port};
+               my $service_name    = 
$connect_method_info->{$connect_method_id}{servicename};
+               my $startup_script  = 
$connect_method_info->{$connect_method_id}{startupscript};
+               my $install_script  = 
$connect_method_info->{$connect_method_id}{installscript};
+               my $disabled        = 
$connect_method_info->{$connect_method_id}{connectmethodmap}{disabled};
+               
+               if ($disabled) {
+                       # TODO: Add code to disable the service, close the 
firewall port, etc
+                       notify($ERRORS{'OK'}, 0, "skipping '$name' connect 
method configuration, it should be disabled on $computer_node_name");
+               }
+               else {
+                       # Attempt to start and configure the connect method
+                       my $service_started = 0;
+                       
+                       # Attempt to start the service if the service name has 
been defined for the connect method
+                       if ($service_name) {
+                               # Check if service exists
+                               notify($ERRORS{'DEBUG'}, 0, "checking if 
'$service_name' service exists for '$name' connect method on 
$computer_node_name");
+                               if ($self->service_exists($service_name)) {
+                                       notify($ERRORS{'DEBUG'}, 0, "attempting 
to start '$service_name' service for '$name' connect method on 
$computer_node_name");
+                                       if 
($self->start_service($service_name)) {
+                                               notify($ERRORS{'OK'}, 0, 
"'$service_name' started on $computer_node_name");
+                                               $service_started = 1;
+                                       }
+                                       else {
+                                               notify($ERRORS{'WARNING'}, 0, 
"failed to start '$service_name' service for '$name' connect method on 
$computer_node_name");
                                        }
                                }
+                               #elsif ($install_script) {
+                               #       notify($ERRORS{'DEBUG'}, 0, 
"'$service_name' service for '$name' connect method does not exist on 
$computer_node_name, attempting to execute connect method install script");
+                               #       my ($install_exit_status, 
$install_output) = $self->execute($install_script, 1, 600, 1);
+                               #       if (!defined($install_output)) {
+                               #               notify($ERRORS{'WARNING'}, 0, 
"failed to run command to execute install script for '$name' connect method on 
$computer_node_name, command: '$install_script'");
+                               #       }
+                               #       else {
+                               #               notify($ERRORS{'OK'}, 0, 
"executed install script for '$name' connect method on $computer_node_name, 
command: '$install_script', exit status: $install_exit_status, output:\n" . 
join("\n", @$install_output));
+                               #               
+                               #               if 
($self->service_exists($service_name)) {
+                               #                       if 
($self->start_service($service_name)) {
+                               #                               
notify($ERRORS{'OK'}, 0, "'$service_name' started on $computer_node_name");
+                               #                               
$service_started = 1;
+                               #                       }
+                               #                       else {
+                               #                               
notify($ERRORS{'WARNING'}, 0, "failed to start '$service_name' service after 
executing install script for '$name' connect method on $computer_node_name");
+                               #                       }
+                               #               }
+                               #               else {
+                               #                       
notify($ERRORS{'WARNING'}, 0, "'$service_name' service does NOT exist after 
executing install script for '$name' connect method on $computer_node_name");
+                               #               }
+                               #       }
+                               #}
                                else {
-                                       notify($ERRORS{'WARNING'}, 0, "Service 
$servicename does not exist on $computer_node_name");
+                                       notify($ERRORS{'WARNING'}, 0, 
"'$service_name' service for '$name' connect method does NOT exist on 
$computer_node_name, connect method install script is not defined");
                                }
                        }
-                       else {
-                               notify($ERRORS{'WARNING'}, 0, "service_exists 
not implemented by OS module" . ref($self));
-                       }
-               }
-               
-               if ( !$service_started && defined 
($$connect_methods{$CMid}{startupscript} ) ) {
-                       notify($ERRORS{'OK'}, 0, "startupscript exists and 
service NOT started ");
                        
-                       #Service command did not work or does not exist
-                       # Try to use startup script
-                       my $cmd = $$connect_methods{$CMid}{startupscript} . " 
start";
-                       notify($ERRORS{'OK'}, 0, "service not started, attempt 
to run $cmd ");
-                       if( $self->can("execute") ) {
-                               if( $self->execute($cmd, 1) ){
-                                       $service_started = 1;   
-                               }       
-                       }
-                       else {
-                               notify($ERRORS{'OK'}, 0, "execute routing not 
available by module" . ref($self) );      
+                       # Run the startup script if the service is not started
+                       if (!$service_started && defined($startup_script)) {
+                               notify($ERRORS{'DEBUG'}, 0, "attempting to run 
startup script '$startup_script' for '$name' connect method on 
$computer_node_name");
+                               my ($startup_exit_status, $startup_output) = 
$self->execute($startup_script, 1);
+                               if (!defined($startup_output)) {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to run command to execute startup script '$startup_script' for '$name' connect 
method on $computer_node_name, command: '$startup_script'");
+                               }
+                               elsif ($startup_exit_status == 0){
+                                       notify($ERRORS{'OK'}, 0, "executed 
startup script '$startup_script' for '$name' connect method on 
$computer_node_name, command: '$startup_script', exit status: 
$startup_exit_status, output:\n" . join("\n", @$startup_output));       
+                               }
+                               else {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to execute startup script '$startup_script' for '$name' connect method on 
$computer_node_name, command: '$startup_script', exit status: 
$startup_exit_status, output:\n" . join("\n", @$startup_output));
+                               }
                        }
-               }       
-               
-               if ( $service_started ) {
-                       #open firewall port
-                       notify($ERRORS{'OK'}, 0, "service started ");
-                       if($self->can("enable_firewall_port")) {
-                               notify($ERRORS{'OK'}, 0, "trying to enable 
firewall port $port on $computer_node_name ");
-                               if(!$self->enable_firewall_port($port)) {
-                                       notify($ERRORS{'CRITICAL'}, 0, "Failed 
to enable firewall Connect Method $CMid $description on $computer_node_name");
+                       
+                       # Open the firewall port
+                       if (defined($port)) {
+                               notify($ERRORS{'DEBUG'}, 0, "attempting to open 
firewall port $port on $computer_node_name for '$name' connect method");
+                               if ($self->enable_firewall_port($protocol, 
$port, "$remote_ip/24", 1)) {
+                                       notify($ERRORS{'OK'}, 0, "opened 
firewall port $port on $computer_node_name for '$name' connect method");
+                               }
+                               else {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to open firewall port $port on $computer_node_name for '$name' connect method");
                                }
                        }
                }
-               else {
-                       notify($ERRORS{'WARNING'}, 0, "Connect Method $CMid 
$description failed to start on $computer_node_name");
-               }
        }
-       
+
        return 1;       
 }
 
@@ -1901,10 +2109,10 @@ sub process_connect_methods {
 sub is_user_connected {
        
        my $self = shift;
-        if (ref($self) !~ /VCL::Module/i) {
-                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-                return;
-        }
+       if (ref($self) !~ /VCL::Module/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
        my $time_limit = shift;
        if ( !$time_limit ) {
                notify($ERRORS{'WARNING'}, 0, "time_limit variable not passed 
as an argument");
@@ -1912,7 +2120,7 @@ sub is_user_connected {
        }
 
        my $request_id           = $self->data->get_request_id();       
-        my $computer_node_name   = $self->data->get_computer_node_name();
+       my $computer_node_name   = $self->data->get_computer_node_name();
        my $request_state_name   = $self->data->get_request_state_name();
        my $user_unityid         = $self->data->get_user_login_id();
        my $computer_ip_address  = $self->data->get_computer_ip_address();
@@ -1920,41 +2128,41 @@ sub is_user_connected {
        my $connect_methods      = $self->data->get_connect_methods();  
        
        my $start_time    = time();
-        my $time_exceeded = 0;
-        my $break         = 0;
-        my $ret_val       = "no";
-
-        # Figure out number of loops for log messages
-        my $maximum_loops = $time_limit * 2;
-        my $loop_count    = 0;
+       my $time_exceeded = 0;
+       my $break         = 0;
+       my $ret_val       = "no";
+
+       # Figure out number of loops for log messages
+       my $maximum_loops = $time_limit * 2;
+       my $loop_count    = 0;
        
        while (!$break) {
-                $loop_count++;
+               $loop_count++;
 
-                notify($ERRORS{'OK'}, 0, "checking for connection by 
$user_unityid on $computer_node_name, attempt $loop_count ");
+               notify($ERRORS{'OK'}, 0, "checking for connection by 
$user_unityid on $computer_node_name, attempt $loop_count ");
 
-                if (is_request_deleted($request_id)) {
-                        notify($ERRORS{'OK'}, 0, "user has deleted request");
-                        $break   = 1;
-                        $ret_val = "deleted";
-                        return $ret_val;
-                }
+               if (is_request_deleted($request_id)) {
+                       notify($ERRORS{'OK'}, 0, "user has deleted request");
+                       $break   = 1;
+                       $ret_val = "deleted";
+                       return $ret_val;
+               }
                
                $time_exceeded = time_exceeded($start_time, $time_limit);
-                if ($time_exceeded) {
-                        notify($ERRORS{'OK'}, 0, "$time_limit minute time 
limit exceeded begin cleanup process");
-                        #time_exceeded, begin cleanup process
-                        $break = 1;
-                        if ($request_state_name =~ /reserved/) {
-                                notify($ERRORS{'OK'}, 0, "user never logged in 
returning nologin");
-                                $ret_val = "nologin";
-                        }
-                        else {
-                                $ret_val = "timeout";
-                        }
-                        return $ret_val;
-                } ## end if ($time_exceeded)
-               else {    #time not exceeded check for connection
+               if ($time_exceeded) {
+                       notify($ERRORS{'OK'}, 0, "$time_limit minute time limit 
exceeded begin cleanup process");
+                       # time_exceeded, begin cleanup process
+                       $break = 1;
+                       if ($request_state_name =~ /reserved/) {
+                               notify($ERRORS{'OK'}, 0, "user never logged in 
returning nologin");
+                               $ret_val = "nologin";
+                       }
+                       else {
+                               $ret_val = "timeout";
+                       }
+                       return $ret_val;
+               } ## end if ($time_exceeded)
+               else {    # time not exceeded check for connection
                        foreach my $CMid (sort keys %{$connect_methods} ) {
                                if($self->can("check_connection_on_port")) {
                                        
if(defined($$connect_methods{$CMid}{port}) && $$connect_methods{$CMid}{port}) {
@@ -1974,8 +2182,8 @@ sub is_user_connected {
                        }
                }
                notify($ERRORS{'DEBUG'}, 0, "sleeping for 20 seconds");
-                sleep 20;
-       }       
+               sleep 20;
+       }
        return $ret_val;
 }
 

Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1179363&r1=1179362&r2=1179363&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Wed Oct  5 
18:22:54 2011
@@ -3044,41 +3044,42 @@ EOF
 =cut
 
 sub service_exists {
-        my $self = shift;
-        if (ref($self) !~ /linux/i) {
-                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-                return;
-        }
-
-        my $management_node_keys = $self->data->get_management_node_keys();
-        my $computer_node_name   = $self->data->get_computer_node_name();
-
-        my $service_name = shift;
-        if (!$service_name) {
-                notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
-                return;
-        }
-
+       my $self = shift;
+       if (ref($self) !~ /linux/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $management_node_keys = $self->data->get_management_node_keys();
+       my $computer_node_name   = $self->data->get_computer_node_name();
+       
+       my $service_name = shift;
+       if (!$service_name) {
+               notify($ERRORS{'WARNING'}, 0, "service name was not passed as 
an argument");
+               return;
+       }
+       
        my $command = "/sbin/chkconfig --list $service_name";
-       my ($status, $output) = run_ssh_command($computer_node_name, 
$management_node_keys, $command, '', '', 1);
-       if (defined($output) && grep(/error reading information on service/i, 
@{$output})) {
-                notify($ERRORS{'DEBUG'}, 0, "service does not exist: 
$service_name");
-                return 0;
-        }
-        elsif (defined($status) && $status == 0) {
-                notify($ERRORS{'DEBUG'}, 0, "service exists: $service_name");
-        }
-        elsif (defined($status)) {
-                notify($ERRORS{'WARNING'}, 0, "unable to determine if service 
exists: $service_name, exit status: $status, output:\n@{$output}");
-                return;
-        }
-        else {
-                notify($ERRORS{'WARNING'}, 0, "unable to run ssh command to 
determine if service exists");
-                return;
-        }
-
-        return 1;
+       my ($exit_status, $output) = run_ssh_command($computer_node_name, 
$management_node_keys, $command, '', '', 1);
+       if (!defined($output)) {
+               notify($ERRORS{'WARNING'}, 0, "failed to execute command to 
determine if '$service_name' service exists on $computer_node_name");
+               return;
+       }
+       elsif (grep(/error reading information on service/i, @$output)) {
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not 
exist on $computer_node_name");
+               return 0;
+       }
+       elsif ($exit_status == 0 || grep(/not referenced in any runlevel/i, 
@$output)) {
+               # chkconfig may display the following if the service exists but 
has not been added:
+               # service ext_sshd supports chkconfig, but is not referenced in 
any runlevel (run 'chkconfig --add ext_sshd')
+               notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists but 
is not referenced in any runlevel");
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "unable to determine if 
'$service_name' service exists, exit status: $exit_status, output:\n" . 
join("\n", @$output));
+               return;
+       }
        
+       return 1;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -3381,9 +3382,9 @@ sub get_total_memory {
 
 =head2 enable_firewall_port
  
-  Parameters  : none
-  Returns     : 1 successful, 0 failed
-  Description : updates iptables for given port for collect IPaddress range 
and mode
+  Parameters  : $protocol, $port, $scope (optional), $overwrite_existing 
(optional), $name (optional), $description (optional)
+  Returns     : boolean
+  Description : Updates iptables for given port for collect IPaddress range 
and mode
  
 =cut
 
@@ -3394,56 +3395,42 @@ sub enable_firewall_port {
       return;
    }
        
-       my $port = shift;
-       if(!$port) {
-               notify($ERRORS{'CRITICAL'}, 0, "Input variable port was not 
passed in as an argument");
-               return 0;
-       } 
-       
-       my $mode = shift;
-       if(!$mode) {
-               notify($ERRORS{'DEBUG'}, 0, "firewall mode not passed in as an 
argument setting to loose");
-               $mode = "medium";
+       my ($protocol, $port, $scope_argument, $overwrite_existing, $name, 
$description) = @_;
+       if (!defined($protocol) || !defined($port)) {
+               notify($ERRORS{'WARNING'}, 0, "protocol and port arguments were 
not supplied");
+               return;
        }
        
    my $computer_node_name = $self->data->get_computer_node_name();
-       my $remote_ip = $self->data->get_reservation_remote_ip();
        
-       my $scope;
-       my $command;
-               
-       if ( $mode =~ /loose/i ) {
-               $command = "/sbin/iptables -I INPUT 1 -m state --state 
NEW,RELATED,ESTABLISHED -m tcp -p tcp --dport $port -j ACCEPT";
-       }        
-       elsif($mode =~ /medium/i) {     
-               $scope = "$remote_ip/16";
-               $command = "/sbin/iptables -I INPUT 1 -s $scope -m state 
--state NEW,RELATED,ESTABLISHED -m tcp -p tcp --dport $port -j ACCEPT";
-       }
-       elsif( $mode =~ /tight/i) {
-               $scope = "$remote_ip/24";
-               $command = "/sbin/iptables -I INPUT 1 -s $scope -m state 
--state NEW,RELATED,ESTABLISHED -m tcp -p tcp --dport $port -j ACCEPT";
-       }
-       elsif( $mode =~ /locked/i) {
-               $command = "/sbin/iptables -I INPUT 1 -s $remote_ip -m state 
--state NEW,RELATED,ESTABLISHED -m tcp -p tcp --dport $port -j ACCEPT";
-       }
-
-       #copy original config
-       my $cp_iptables_config = "cp /etc/sysconfig/iptables 
/etc/sysconfig/iptables_pre_$port";
-       my ($status_cp, $output_cp) = $self->execute($cp_iptables_config);      
-       if (defined $status_cp && $status_cp == 0) {
-               notify($ERRORS{'DEBUG'}, 0, "executed command 
$cp_iptables_config on $computer_node_name");
+       $protocol = lc($protocol);
+       
+       my $command = "/sbin/iptables -I INPUT 1 -m state --state 
NEW,RELATED,ESTABLISHED -m $protocol -p $protocol --dport $port -j ACCEPT";
+       
+       if ($scope_argument) {
+               $command .= " -s $scope_argument";
+       }
+
+       # Make backup copy of original iptables configuration
+       my $iptables_backup_file_path = "/etc/sysconfig/iptables_pre_$port";
+       if ($self->copy_file("/etc/sysconfig/iptables", 
$iptables_backup_file_path)) {
+               notify($ERRORS{'DEBUG'}, 0, "backed up original iptables file 
to: '$iptables_backup_file_path'");
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to back up original 
iptables file to: '$iptables_backup_file_path'");
        }
        
        # Add rule
+       notify($ERRORS{'DEBUG'}, 0, "attempting to execute command on 
$computer_node_name: '$command'");
        my ($status, $output) = $self->execute($command);       
        if (defined $status && $status == 0) {
-               notify($ERRORS{'DEBUG'}, 0, "executed command $command on 
$computer_node_name");
+               notify($ERRORS{'DEBUG'}, 0, "executed command on 
$computer_node_name: '$command'");
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "output from iptables:" . 
join("\n", @$output));
+               notify($ERRORS{'WARNING'}, 0, "output from iptables:\n" . 
join("\n", @$output));
        }
        
-       #Save rules to sysconfig/iptables -- incase of reboot
+       # Save rules to sysconfig/iptables -- incase of reboot
        my $iptables_save_cmd = "/sbin/iptables-save > /etc/sysconfig/iptables";
        my ($status_save, $output_save) = $self->execute($iptables_save_cmd);   
        if (defined $status_save && $status_save == 0) {

Modified: incubator/vcl/trunk/managementnode/lib/VCL/utils.pm
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1179363&r1=1179362&r2=1179363&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/utils.pm Wed Oct  5 18:22:54 2011
@@ -117,6 +117,7 @@ our @EXPORT = qw(
   get_computer_ids
   get_computer_info
   get_computers_controlled_by_MN
+  get_connect_method_info
   get_current_file_name
   get_current_package_name
   get_current_subroutine_name
@@ -4645,8 +4646,8 @@ sub get_request_info {
                my $computer_info = get_computer_info($computer_id, 1);
                $request_info{reservation}{$reservation_id}{computer} = 
$computer_info;
 
-               my $connect_methods = get_connect_methods($image_id, 
$imagerevision_id);
-               $request_info{reservation}{$reservation_id}{connect_methods} = 
$connect_methods;
+               my $connect_method_info = 
get_connect_method_info($imagerevision_id);
+               $request_info{reservation}{$reservation_id}{connect_methods} = 
$connect_method_info;
                
        }    # Close loop through selected rows
        
@@ -4797,7 +4798,7 @@ sub get_request_info {
                
$request_info{reservation}{$reservation_id}{computer}{SHORTNAME} = 
$computer_shortname;
 
                # Add the managementnode info to the hash
-               my $management_node_id   = 
$request_info{reservation}{$reservation_id}{managementnodeid};
+               my $management_node_id = 
$request_info{reservation}{$reservation_id}{managementnodeid};
                my $management_node_info = 
get_management_node_info($management_node_id);
                if (!$management_node_info) {
                        notify($ERRORS{'WARNING'}, 0, "failed to retrieve 
management node info");
@@ -5061,6 +5062,7 @@ sub get_image_info {
                'image',
                'platform',
                'OS',
+               'OStype',
                'module',
        );
        
@@ -5084,12 +5086,14 @@ FROM
 image,
 platform,
 OS,
+OStype,
 module
 
 WHERE
 platform.id = image.platformid
 AND OS.id = image.OSid
 AND module.id = OS.moduleid
+AND OS.type = OStype.name
 AND 
 EOF
        
@@ -5132,7 +5136,7 @@ EOF
                if ($table eq $tables[0]) {
                        $image_info->{$column} = $value;
                }
-               elsif ($table eq 'module') {
+               elsif ($table =~ /^(module|OStype)$/) {
                        $image_info->{OS}{$table}{$column} = $value;
                }
                else {
@@ -5586,6 +5590,8 @@ sub run_ssh_command {
        $timeout_seconds = 0 if (!$timeout_seconds);
        $identity_paths = $ENV{management_node_info}{keys} if (!defined 
$identity_paths || length($identity_paths) == 0);
        
+#return VCL::Module::OS::execute($node, $command, $output_level, 
$timeout_seconds, $max_attempts, $port, $user);
+       
        # TODO: Add ssh path to config file and set global variable
        # Locate the path to the ssh binary
        my $ssh_path;
@@ -9564,8 +9570,7 @@ sub xmlrpc_call {
                        "password: $XMLRPC_PASS\n" .
                        "arguments: " . join(", ", @arguments) . "\n" .
                        "fault code: " . $response->code . "\n" .
-                       "fault string: " . $response->string .
-                       format_data($response)
+                       "fault string: " . $response->string
                );
                $ENV{rpc_xml_error} = $response->string;
                return;
@@ -10667,83 +10672,119 @@ sub kill_child_processes {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 get_connect_method
+=head2 get_connect_method_info
 
- Parameters  : reservationid
+ Parameters  : $imagerevision_id
  Returns     : hash reference
- Description : Returns the contents of connect method for reservationid.
+ Description : Returns the connect methods for the image revision specified as
+               the argument.
 
 =cut
 
-sub get_connect_methods {
+sub get_connect_method_info {
+       my ($imagerevision_id) = @_;
+       if (!defined($imagerevision_id)) {
+               notify($ERRORS{'WARNING'}, 0, "imagerevision ID argument was 
not supplied");
+               return;
+       }
+       
+       my $imagerevision_info = get_imagerevision_info($imagerevision_id);
+       
+       notify($ERRORS{'DEBUG'}, 0, "attempting to retrieve connect method 
info:\n" .
+               "imagerevision: $imagerevision_id - " . 
$imagerevision_info->{imagename} . "\n" .
+               "OS: " . $imagerevision_info->{image}{OS}{id} . " - " . 
$imagerevision_info->{image}{OS}{name} . "\n" .
+               "OS type: " . $imagerevision_info->{image}{OS}{OStype}{id} . " 
- " . $imagerevision_info->{image}{OS}{OStype}{name}
+       );
+       
+       # Get a hash ref containing the database column names
+       my $database_table_columns = get_database_table_columns();
+       
+       my @tables = (
+               'connectmethod',
+               'connectmethodmap'
+       );
+       
+       # Construct the select statement
+       my $select_statement = "SELECT DISTINCT\n";
+       
+       # Get the column names for each table and add them to the select 
statement
+       for my $table (@tables) {
+               my @columns = @{$database_table_columns->{$table}};
+               for my $column (@columns) {
+                       $select_statement .= "$table.$column AS 
'$table-$column',\n";
+               }
+       }
+       
+       # Remove the comma after the last column line
+       $select_statement =~ s/,$//;
+       
+       # Complete the select statement
+       $select_statement .= <<EOF;
+FROM
+connectmethod,
+connectmethodmap,
+imagerevision
 
-        my ($imageid, $imagerevisionid) = @_;
-        my ($calling_package, $calling_filename, $calling_line, $calling_sub) 
= caller(0);
+LEFT JOIN image ON (image.id = imagerevision.imageid)
+LEFT JOIN OS ON (OS.id = image.OSid)
+LEFT JOIN OStype ON (OStype.name = OS.type)
 
-        if (!defined($imagerevisionid)) {
-                notify($ERRORS{'WARNING'}, 0, "$calling_sub $calling_package 
missing mandatory variable: imagerevisionid ");
-                return 0;
-        }
-        
-        if (!defined($imageid)) {
-                notify($ERRORS{'WARNING'}, 0, "$calling_sub $calling_package 
missing mandatory variable: imageid ");
-                return 0;
-        }
-
-        my $select_statement = "
-        SELECT DISTINCT
-        c.id AS CM_id,
-        c.description AS CM_description,
-        c.port AS CM_port,
-        c.servicename AS CM_servicename,
-        c.startupscript AS CM_startupscript,
-        cm.autoprovisioned AS CM_autoprovisioned,
-        cm.disabled AS CM_disabled
-        FROM
-        connectmethod c,
-        connectmethodmap cm,
-        image i
-        LEFT JOIN OS o ON (o.id = i.OSid)
-        LEFT JOIN OStype ot ON (ot.name = o.type)
-        WHERE 
-        i.id = $imageid AND
-        cm.connectmethodid = c.id AND
-        cm.autoprovisioned IS NULL AND
-        (cm.OStypeid = ot.id OR
-        cm.OSid = o.id OR 
-        cm.imagerevisionid = $imagerevisionid)
-        ORDER BY cm.disabled, c.description";
+WHERE
+connectmethodmap.connectmethodid = connectmethod.id
+AND imagerevision.id = $imagerevision_id
+AND connectmethodmap.autoprovisioned IS NOT NULL
+AND (
+       connectmethodmap.OStypeid = OStype.id
+       OR connectmethodmap.OSid = OS.id 
+       OR connectmethodmap.imagerevisionid = imagerevision.id
+)
 
-        # Call the database select subroutine
-        # This will return an array of one or more rows based on the select 
statement
-        my @selected_rows = database_select($select_statement);
+ORDER BY
+connectmethod.id,
+connectmethodmap.imagerevisionid,
+connectmethodmap.OSid,
+connectmethodmap.OStypeid,
+connectmethodmap.disabled
+EOF
 
-        my @ret_array;
-        my %connect_info;
+       # Call the database select subroutine
+       my @selected_rows = database_select($select_statement);
        
-               # Check to make sure 1 or more rows were returned
-        if (scalar @selected_rows > 0) {
-                # It contains a hash
-                for (@selected_rows) {
-                        my %connectMethod = %{$_};
-                        next if($connectMethod{CM_disabled});
-                        my $CMid = $connectMethod{CM_id};
-                        $connect_info{$CMid}{"id"} = $CMid;
-                        $connect_info{$CMid}{"description"} = 
$connectMethod{CM_description};
-                        $connect_info{$CMid}{"port"} = $connectMethod{CM_port};
-                        $connect_info{$CMid}{"servicename"} = 
$connectMethod{CM_servicename};
-                        $connect_info{$CMid}{"startupscript"} = 
$connectMethod{CM_startupscript};
-                        $connect_info{$CMid}{"autoprovisioned"} = 
$connectMethod{CM_autoprovisioned};
+       # Transform the array of database rows into a hash
+       my $connect_method_info = {};
+       
+       for my $row (@selected_rows) {  
+               notify($ERRORS{'DEBUG'}, 0, $row->{"connectmethod-name"} . ": " 
.
+               "connectmethodid=" . $row->{"connectmethod-id"} . ", " .
+               "OStypeid=" . ($row->{"connectmethodmap-OStypeid"} || 'NULL') . 
", " .
+               "OSid=" . ($row->{"connectmethodmap-OSid"} || 'NULL') . ", " .
+               "imagerevisionid=" . 
($row->{"connectmethodmap-imagerevisionid"} || 'NULL') . ", " .
+               "disabled=" . $row->{"connectmethodmap-disabled"});
+               
+               my $connectmethod_id = $row->{'connectmethod-id'};
+               
+               # Loop through all the columns returned
+               for my $key (keys %$row) {
+                       next if $key eq 'connectmethod-connecttext';
                        
-                       notify($ERRORS{'OK'}, 0, "CONNECT METHOD CMid= $CMid 
description= $connect_info{$CMid}{description}");
-        
-                }
-                
-                return \%connect_info;
-        }       
-        
-        return();       
+                       my $value = $row->{$key};
+                       
+                       # Split the table-column names
+                       my ($table, $column) = $key =~ /^([^-]+)-(.+)/;
+                       
+                       # Add the values for the primary table to the hash
+                       # Add values for other tables under separate keys
+                       if ($table eq $tables[0]) {
+                               
$connect_method_info->{$connectmethod_id}{$column} = $value;
+                       }
+                       else {
+                               
$connect_method_info->{$connectmethod_id}{$table}{$column} = $value;
+                       }
+               }
+       }
 
+       notify($ERRORS{'DEBUG'}, 0, "retrieved connect method info:\n" . 
format_data($connect_method_info));
+       return $connect_method_info;
 }
 
 #/////////////////////////////////////////////////////////////////////////////


Reply via email to