You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2014/06/16 21:51:54 UTC

svn commit: r1602979 [2/2] - in /vcl/trunk/managementnode/lib/VCL: Module/OS.pm Module/OS/Linux.pm Module/OS/Windows.pm new.pm utils.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1602979&r1=1602978&r2=1602979&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Mon Jun 16 19:51:54 2014
@@ -790,6 +790,16 @@ sub post_load {
 		notify($ERRORS{'WARNING'}, 0, "failed to rename My Computer");
 	}
 
+=item *
+
+ Check if the RDP port configured on the computer matches the RDP connect method
+
+=cut
+
+	if (!$self->check_rdp_port_configuration()) {
+		return 0;
+	}
+
 #=item *
 #
 #Disable NetBIOS
@@ -899,9 +909,9 @@ sub post_load {
 
 =head2 reserve
 
- Parameters  :
- Returns     :
- Description :
+ Parameters  : none
+ Returns     : boolean
+ Description : Performs the steps necessary to reserve a computer for a user.
 
 =cut
 
@@ -911,12 +921,21 @@ sub reserve {
 		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
 		return;
 	}
-
-	my $request_forimaging   = $self->data->get_request_forimaging();
-	my $reservation_password = $self->data->get_reservation_password();
-
+	
+	# Call OS.pm's reserve subroutine
+	$self->SUPER::reserve() || return;
+	
 	notify($ERRORS{'OK'}, 0, "beginning Windows reserve tasks");
-
+	
+	# Generate a reservation password
+	if (!$self->check_reservation_password()) {
+		notify($ERRORS{'WARNING'}, 0, "failed to generate a reservation password");
+		return;
+	}
+	
+	my $request_forimaging = $self->data->get_request_forimaging();
+	my $reservation_password = $self->data->get_reservation_password();
+	
 	# Check if this is an imaging request or not
 	if ($request_forimaging) {
 		# Imaging request, don't create account, set the Administrator password
@@ -932,8 +951,7 @@ sub reserve {
 			return 0;
 		}
 	}
-
-	notify($ERRORS{'OK'}, 0, "returning 1");
+	
 	return 1;
 } ## end sub reserve
 
@@ -1078,7 +1096,6 @@ sub grant_access {
 		return;
 	}
 
-	my $management_node_keys = $self->data->get_management_node_keys();
 	my $computer_node_name   = $self->data->get_computer_node_name();
 	my $system32_path        = $self->get_system32_path();
 	my $request_forimaging   = $self->data->get_request_forimaging();
@@ -1770,7 +1787,7 @@ sub create_user {
 		$username = $self->data->get_user_login_id();
 	}
 	if (!$password) {
-		$password = $self->data->get_reservation_password();
+		$password = $self->data->get_reservation_password() || return;
 	}
 	
 	# If imagemeta allows rootaccess, check the adminoverride variable
@@ -7748,12 +7765,13 @@ sub apply_security_templates {
 		# Note: secedit.exe returns exit status 3 if a warning occurs, this will appear in the log file:
 		# Task is completed. Warnings occurred for some attributes during this operation. It's ok to ignore.
 		my $secedit_command = "$secedit_exe /configure /cfg \"$inf_target_path\" /db $secedit_db /log $secedit_log /overwrite /quiet";
+		
 		my ($secedit_exit_status, $secedit_output) = run_ssh_command($computer_node_name, $management_node_keys, $secedit_command, '', '', 0);
 		if (defined($secedit_exit_status) && ($secedit_exit_status == 0 || $secedit_exit_status == 3)) {
 			notify($ERRORS{'OK'}, 0, "ran secedit.exe to apply $inf_file_name");
 		}
 		elsif (defined($secedit_exit_status)) {
-			notify($ERRORS{'WARNING'}, 0, "failed to run secedit.exe to apply $inf_target_path, exit status: $secedit_exit_status, output:\n" . join("\n", @$secedit_output));
+			notify($ERRORS{'WARNING'}, 0, "failed to run secedit.exe to apply $inf_target_path, exit status: $secedit_exit_status, command: $secedit_command, output:\n" . join("\n", @$secedit_output));
 			$error_occurred++;
 		}
 		else {
@@ -8990,19 +9008,13 @@ sub user_logged_in {
 		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 $system32_path        = $self->get_system32_path() || return;
-
+	
 	# Attempt to get the username from the arguments
 	# If no argument was supplied, use the user specified in the DataStructure
 	my $username = shift;
 	
-	# Remove spaces from beginning and end of username argument
-	# Fixes problem if string containing only spaces is passed
-	$username =~ s/(^\s+|\s+$)//g if $username;
-	
 	# Check if username argument was passed
 	if (!$username) {
 		if ($self->data->get_request_forimaging()) {
@@ -9012,32 +9024,71 @@ sub user_logged_in {
 			$username = $self->data->get_user_login_id();
 		}
 	}
-	notify($ERRORS{'DEBUG'}, 0, "checking if $username is logged in to $computer_node_name");
+	
+	my @logged_in_users = $self->get_logged_in_users();
+	if (grep { $username eq $_ } @logged_in_users) {
+		notify($ERRORS{'DEBUG'}, 0, "$username is logged in to $computer_node_name");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "$username is NOT logged in to $computer_node_name");
+		return 0;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_logged_in_users
+
+ Parameters  : none
+ Returns     : array
+ Description : Retrieves the names of users logged in to the computer.
+
+=cut
+
+sub get_logged_in_users {
+	my $self = shift;
+	if (ref($self) !~ /windows/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();
+	my $system32_path        = $self->get_system32_path() || return;
 
 	# Run qwinsta.exe to display terminal session information
 	# Set command timeout argument because this command occasionally hangs
-	my ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, "$system32_path/qwinsta.exe", '', '', 1, 60);
-	if ($exit_status > 0) {
-		notify($ERRORS{'WARNING'}, 0, "failed to run qwinsta.exe on $computer_node_name, exit status: $exit_status, output:\n@{$output}");
+	my $command = "$system32_path/qwinsta.exe";
+	my ($exit_status, $output) = $self->execute({
+		command => $command,
+		timeout => 60,
+	});
+	
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to run qwinsta.exe command on $computer_node_name");
 		return;
 	}
-	elsif (!defined($exit_status)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to run qwinsta.exe SSH command on $computer_node_name");
+	elsif (!grep(/USERNAME/, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to retrieve logged in users on $computer_node_name, command: $command, output:\n" . join("\n", @$output));
 		return;
 	}
-	
-	# Find lines in qwinsta.exe output indicating a logged in user, lines may look like this:
-	# ' rdp-tcp#2         root                      2  Active  rdpwd'
-	# '>console           root                      0  Active  wdcon'
-	my @user_connection_lines = grep(/[\s>]+(\S+)\s+($username)\s+(\d+)\s+(Active)/, @{$output});
-	if (@user_connection_lines) {
-		notify($ERRORS{'OK'}, 0, "$username appears to be logged in on $computer_node_name:\n" . join("\n", @user_connection_lines));
-		return 1;
-	}
-	else {
-		notify($ERRORS{'OK'}, 0, "$username does NOT appear to be logged in on $computer_node_name");
-		return 0;
+
+	# SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
+	# services                                    0  Disc
+	#                   root                      1  Disc
+	# console                                     2  Conn
+	#>rdp-tcp#1         Administrator             3  Active  rdpwd
+	# rdp-tcp#2         test user                 4  Active  rdpwd
+	# rdp-tcp                                 65536  Listen
+	my @usernames;
+	for my $line (@$output) {
+		my ($session_name, $username, $session_id, $state) = $line =~ /^[\s>]([^\s]+)?\s+(.+[^\s])?\s+(\d+)\s+(Active)/i;
+		push @usernames, $username if defined($username);
 	}
+	
+	my $username_count = scalar(@usernames);
+	notify($ERRORS{'DEBUG'}, 0, "$username_count user" . ($username_count == 1 ? '' : 's') . " logged in to $computer_node_name: " . join(', ', @usernames));
+	return @usernames;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -11068,71 +11119,37 @@ sub firewall_compare_update {
       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();
    my $imagerevision_id   = $self->data->get_imagerevision_id();
    my $remote_ip          = $self->data->get_reservation_remote_ip();
-  
-   #collect connection_methods
-   #collect firewall_config
-   #For each port defined in connection_methods
-   #compare rule source address with remote_IP address
-	notify($ERRORS{'OK'}, 0, "pulling connect methods");
-  
-   # Retrieve the connect method info hash
+	
+	if (!$remote_ip) {
+		notify($ERRORS{'WARNING'}, 0, "unable to update firewall on $computer_node_name, remote IP could not be retrieved for reservation");
+      return;
+	}
+	
+   # Retrieve the connect method info
    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");
+      notify($ERRORS{'WARNING'}, 0, "failed to retrieve connect method info for image revision $imagerevision_id");
       return;
    }
-
-   # Retrieve the firewall configuration
+	
+   # Retrieve the firewall configuration from the computer
    my $firewall_configuration = $self->get_firewall_configuration() || return;
-
+	
+	# Loop through the connect methods, check to make sure firewall is open for remote IP
    for my $connect_method_id (sort keys %{$connect_method_info} ) {
+      my $connect_method_name = $connect_method_info->{$connect_method_id}{name};
+      my $protocol            = $connect_method_info->{$connect_method_id}{protocol} || 'TCP';
+      my $port                = $connect_method_info->{$connect_method_id}{port};
 		
-      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 $scope;
-		
-		next if ( !$port );
-
-     # $protocol = lc($protocol);
-
-		my $existing_scope = $firewall_configuration->{$protocol}{$port}{scope} || '';
-		if(!$existing_scope ) {
-			notify($ERRORS{'WARNING'}, 0, "No existing scope defined for protocol= $protocol port= $port ");
-			return 1;
-      }
-		else {
-            my $parsed_existing_scope = $self->parse_firewall_scope($existing_scope);
-            if (!$parsed_existing_scope) {
-                notify($ERRORS{'WARNING'}, 0, "failed to parse existing firewall scope: '$existing_scope'");
-                return;
-            }
-            $scope = $self->parse_firewall_scope("$remote_ip,$existing_scope");
-            if (!$scope) {
-                notify($ERRORS{'WARNING'}, 0, "failed to parse firewall scope argument appended with existing scope: '$remote_ip,$existing_scope'");
-                return;
-            }
-
-            if ($scope eq $parsed_existing_scope) {
-                notify($ERRORS{'DEBUG'}, 0, "firewall is already open on $computer_node_name, existing scope matches scope argument:\n" .
-               "name: '$name'\n" .
-               "protocol: $protocol\n" .
-               "port/type: $port\n" .
-               "scope: $scope\n");
-                return 1;
-            }
-				else {
-               if ($self->enable_firewall_port($protocol, $port, "$remote_ip/24", 0)) {
-                   notify($ERRORS{'OK'}, 0, "opened firewall port $port on $computer_node_name for $remote_ip $name connect method");
-               }
-            }
-			}
-	
+		next if (!$port);
+		
+		if ($self->enable_firewall_port($protocol, $port, $remote_ip, 0)) {
+			notify($ERRORS{'DEBUG'}, 0, "opened/verified firewall port $port on $computer_node_name for $remote_ip $connect_method_name connect method");
+		}
 	}
 	return 1;
 
@@ -11244,87 +11261,6 @@ sub run_script {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 run_scripts
-
- Parameters  : $stage
- Returns     : boolean
- Description : Runs scripts on the computer intended for the state specified by
-               the argument. The stage argument may be any of the following:
-               -pre_capture
-               -post_load
-               -post_reserve
-               
-               Scripts are stored in various directories under tools matching
-               the OS of the image being loaded. For example, scripts residing
-               in any of the following directories would be executed if the
-               stage argument is 'post_load' and the OS of the image being
-               loaded is Windows XP 32-bit:
-               -tools/Windows/Scripts/post_load
-               -tools/Windows/Scripts/post_load/x86
-               -tools/Windows_Version_5/Scripts/post_load
-               -tools/Windows_Version_5/Scripts/post_load/x86
-               -tools/Windows_XP/Scripts/post_load
-               -tools/Windows_XP/Scripts/post_load/x86
-               
-               The order the scripts are executed is determined by the script
-               file names. The directory where the script resides has no affect
-               on the order. Script files can be named beginning with a number.
-               The scripts sorted numerically and processed from the lowest
-               number to the highest:
-               -1.cmd
-               -50.cmd
-               -100.cmd
-               
-               Scripts which do not begin with a number are sorted
-               alphabetically and processed after any scripts which begin with a
-               number:
-               -1.cmd
-               -50.cmd
-               -100.cmd
-               -Blah.cmd
-               -foo.cmd
-
-=cut
-
-sub run_scripts {
-	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;
-	}
-	
-	# Get the stage argument
-	my $stage = shift;
-	if (!$stage) {
-		notify($ERRORS{'WARNING'}, 0, "unable to run scripts, stage argument was not supplied");
-		return;
-	}
-	elsif ($stage !~ /(pre_capture|post_load|post_reserve)/) {
-		notify($ERRORS{'WARNING'}, 0, "invalid stage argument was supplied: $stage");
-		return;
-	}
-	
-	my $computer_node_name = $self->data->get_computer_node_name();
-	
-	my @computer_tools_files = $self->get_tools_file_paths("/Scripts/$stage/");
-	
-	# Loop through all tools files on the computer
-	for my $computer_tools_file_path (@computer_tools_files) {
-		if ($computer_tools_file_path !~ /\.(cmd|bat)$/i) {
-			notify($ERRORS{'DEBUG'}, 0, "file on $computer_node_name not executed because extension is not .cmd or .bat: $computer_tools_file_path");
-			next;
-		}
-		
-		notify($ERRORS{'DEBUG'}, 0, "executing script on $computer_node_name: $computer_tools_file_path");
-		
-		$self->run_script($computer_tools_file_path);
-	}
-	
-	return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 =head2 install_updates
 
  Parameters  : none
@@ -11975,6 +11911,211 @@ sub get_firewall_state {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 check_rdp_port_configuration
+
+ Parameters  : none
+ Returns     : boolean
+ Description : Checks if the RDP port number configured in the registry matches
+               the port number configured for the RDP connect method. If they
+               don't match, the registry is modified and the TermService service
+               is restarted.
+
+=cut
+
+sub check_rdp_port_configuration {
+	my $self = shift;
+	if (ref($self) !~ /windows/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $imagerevision_id = $self->data->get_imagerevision_id();
+	my $computer_name = $self->data->get_computer_short_name();
+	
+	my $connect_method_info = get_connect_method_info($imagerevision_id);
+	if (!$connect_method_info) {
+		notify($ERRORS{'WARNING'}, 0, "unable to check RDP port, connect method info could not be retrieved for image ID $imagerevision_id");
+		return;
+	}
+	
+	# Find the RDP method, retrieve the port
+	my $connect_method_rdp_port;
+	for my $connect_method_id (keys %$connect_method_info) {
+		my $connect_method_name = $connect_method_info->{$connect_method_id}{name};
+		if ($connect_method_name =~ /^rdp$/i) {
+			$connect_method_rdp_port = $connect_method_info->{$connect_method_id}{port};
+			last;
+		}
+	}
+	if (!defined($connect_method_rdp_port)) {
+		notify($ERRORS{'DEBUG'}, 0, "no connect method exists named 'rdp':\n" . format_data($connect_method_info));
+		return 1;
+	}
+	
+	my $rdp_port_key = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp';
+	my $rdp_port_value = 'PortNumber';
+	
+	my $existing_rdp_port = $self->reg_query($rdp_port_key, $rdp_port_value);
+	if (!defined($existing_rdp_port)) {
+		notify($ERRORS{'WARNING'}, 0, "unable to check RDP port on $computer_name, failed to retrieve existing value from registry");
+		return;
+	}
+	elsif ($existing_rdp_port eq $connect_method_rdp_port) {
+		notify($ERRORS{'DEBUG'}, 0, "existing RDP port value in registry matches connect method port: $connect_method_rdp_port");
+		return 1;
+	}
+	notify($ERRORS{'DEBUG'}, 0, "existing RDP port value in registry $existing_rdp_port does NOT match connect method port $connect_method_rdp_port");
+	
+	# Set the registry key
+	if (!$self->reg_add($rdp_port_key, $rdp_port_value, 'REG_DWORD', $connect_method_rdp_port)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to set RDP port value in registry");
+		return;
+	}
+	
+	# The services that depend on TermService must be stopped first or else the restart will fail
+	$self->stop_service('UmRdpService');
+	$self->stop_service('Mcx2Svc');
+	
+	if ($self->restart_service('TermService')) {
+		notify($ERRORS{'OK'}, 0, "configured $computer_name to use RDP port $connect_method_rdp_port");
+		return 1;
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to configure $computer_name to use RDP port $connect_method_rdp_port, failed to restart Remote Desktop Service (TermService)");
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_port_connection_info
+
+ Parameters  : none
+ Returns     : hash reference
+ Description : Retrieves information about established connections from the
+               computer. A hash is constructed:
+                  {
+                    "TCP" => {
+                      22 => [
+                        {
+                          "local_ip" => "10.25.10.197",
+                          "pid" => 3648,
+                          "remote_ip" => "10.25.0.241",
+                          "remote_port" => 54692
+                        }
+                      ],
+                      3389 => [
+                        {
+                          "local_ip" => "192.168.16.238",
+                          "pid" => 332,
+                          "remote_ip" => "192.168.53.54",
+                          "remote_port" => 55892
+                        }
+                      ]
+                    }
+                  }
+
+=cut
+
+sub get_port_connection_info {
+	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();
+	
+	
+	my $command = "netstat -ano";
+	my ($exit_status, $output) = $self->execute($command, 0);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command: $command");
+		return;
+	}
+	elsif (grep(/^netstat: /, @$output)) {
+		notify($ERRORS{'WARNING'}, 0, "error occurred executing command: '$command', exit status: $exit_status, output:\n" . join("\n", @$output));
+		return;
+	}
+	
+	my $connection_info = {};
+	for my $line (@$output) {
+		# Proto  Local Address          Foreign Address         State           PID
+		# TCP    192.168.1.53:3389      192.168.53.54:55892     ESTABLISHED     332
+		my ($protocol, $local_ip_address, $local_port, $remote_ip_address, $remote_port, $state, $pid) = $line =~ /^\s*(\w+)\s+([\d\.]+):(\d+)\s+([\d\.]+):(\d+)\s+(\w+)\s+(\d+)/i;
+		
+		if (!$state) {
+			#notify($ERRORS{'DEBUG'}, 0, "connection state could not be determined from line:\n$line");
+			next;
+		}
+		elsif ($state !~ /ESTABLISHED/i) {
+			next;
+		}
+		
+		my $connection = {
+			local_ip => $local_ip_address,
+			remote_ip => $remote_ip_address,
+			remote_port => $remote_port,
+		};
+		$connection->{pid} = $pid if $pid;
+		
+		push @{$connection_info->{$protocol}{$local_port}}, $connection;
+	}
+	
+	if ($connection_info) {
+		notify($ERRORS{'DEBUG'}, 0, "retrieved connection info from $computer_node_name:\n" . format_data($connection_info));
+	}
+	else {
+		notify($ERRORS{'DEBUG'}, 0, "did not detect any connections on $computer_node_name");
+	}
+	return $connection_info;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_timezone_offset_minutes
+
+ Parameters  : none
+ Returns     : integer
+ Description : Retrieves the number of minutes the system time of the computer
+               is offset from UTC. It may be positive or negative. This is used
+               to adjust times returned by the computer which are not adjusted
+               to the computer's time zone such as from event log entries.
+
+=cut
+
+sub get_timezone_offset_minutes {
+	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;
+	}
+	
+	return $self->{timezone_offset_minutes} if defined($self->{timezone_offset_minutes});
+	
+	my $system32_path = $self->get_system32_path();
+	
+	my $command = "$system32_path/Wbem/wmic.exe OS Get CurrentTimeZone";
+	my ($exit_status, $output) = $self->execute($command);
+	if (!defined($output)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to execute command to retrieve timezone offset");
+		return;
+	}
+	
+	my ($offset_minutes) = grep(/^-?\d+$/, @$output);
+	if (defined($offset_minutes)) {
+		notify($ERRORS{'DEBUG'}, 0, "retrieved OS timezone offset minutes: $offset_minutes");
+		$self->{timezone_offset_minutes} = $offset_minutes;
+		return $self->{timezone_offset_minutes};
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to retrieve OS timezone offset minutes, command: $command, output:\n" . join("\n", @$output));
+		return;
+	}
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 1;
 __END__
 

Modified: vcl/trunk/managementnode/lib/VCL/new.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/new.pm?rev=1602979&r1=1602978&r2=1602979&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/new.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/new.pm Mon Jun 16 19:51:54 2014
@@ -105,7 +105,7 @@ sub process {
 	my $imagerevision_id                = $self->data->get_imagerevision_id();
 	my $user_standalone                 = $self->data->get_user_standalone();
 	
-	#If reload state is reload and computer is part of block allocation confirm imagerevisionid is the production image.
+	# If reload state is reload and computer is part of block allocation confirm imagerevisionid is the production image.
 	if ($request_state_name eq 'reload' && is_inblockrequest($computer_id)) {
 		notify($ERRORS{'OK'}, 0, "request state is '$request_state_name', computer $computer_id is in blockrequest, making sure reservation is assigned production image revision");
 		my $imagerev_info = get_production_imagerevision_info($image_id);
@@ -898,8 +898,8 @@ sub computer_not_being_used {
 
 =head2 reserve_computer
 
- Parameters  :
- Returns     :
+ Parameters  : none
+ Returns     : boolean
  Description :
 
 =cut
@@ -907,216 +907,80 @@ sub computer_not_being_used {
 sub reserve_computer {
 	my $self = shift;
 
-	my $request_data                    = $self->data->get_request_data();
-	my $request_state_name              = $self->data->get_request_state_name();
 	my $request_id                      = $self->data->get_request_id();
+	my $request_state_name              = $self->data->get_request_state_name();
 	my $request_logid                   = $self->data->get_request_log_id();
-	my $request_forimaging              = $self->data->get_request_forimaging();
-	my $reservation_count               = $self->data->get_reservation_count();
-	my $reservation_id                  = $self->data->get_reservation_id();
 	my $reservation_is_parent           = $self->data->is_parent_reservation;
-	my $computer_id                     = $self->data->get_computer_id();
 	my $computer_short_name             = $self->data->get_computer_short_name();
-	my $computer_type                   = $self->data->get_computer_type();
-	my $computer_ip_address             = $self->data->get_computer_ip_address();
-	my $image_os_name                   = $self->data->get_image_os_name();
 	my $image_prettyname                = $self->data->get_image_prettyname();
-	my $image_os_type                   = $self->data->get_image_os_type();
 	my $user_affiliation_sitewwwaddress = $self->data->get_user_affiliation_sitewwwaddress();
 	my $user_affiliation_helpaddress    = $self->data->get_user_affiliation_helpaddress();
-	my $user_standalone                 = $self->data->get_user_standalone();
 	my $user_email                      = $self->data->get_user_email();
 	my $user_emailnotices               = $self->data->get_user_emailnotices();
 	my $user_imtype_name                = $self->data->get_user_imtype_name();
 	my $user_im_id                      = $self->data->get_user_im_id();
+
+	# Call OS module's reserve subroutine
+	if (!$self->os->reserve()) {
+		$self->reservation_failed("OS module failed to reserve resources for this reservation");
+		return;
+	}
 	
-	notify($ERRORS{'OK'}, 0, "user_standalone=$user_standalone, image OS type=$image_os_type");
+	# Check if this is a parent reservation, only the parent reservation handles notifications
+	if (!$reservation_is_parent) {
+		return 1;
+	}
 	
-	my ($mailstring, $subject, $r);
+	# Retrieve the computer IP address after reserve() is called because it may change
+	# Reserve may retrieve a dynamically assigned IP address and should update the DataStructure object
+	my $computer_ip_address = $self->data->get_computer_ip_address();
 	
-	# check for deletion
+	# Update sublog table with the IP address of the machine
+	if (update_sublog_ipaddress($request_logid, $computer_ip_address)) {
+		notify($ERRORS{'DEBUG'}, 0, "updated computer IP address in sublog table, log ID: $request_logid, IP address: $computer_ip_address");
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "could not update sublog $request_logid for node $computer_short_name IP address $computer_ip_address");
+	}
+
+	# Check if request has been deleted
 	if (is_request_deleted($request_id)) {
-		notify($ERRORS{'OK'}, 0, "user has deleted, quietly exiting");
-		#return 0 and let process routine handle reset computer state
-		return 0;
+		notify($ERRORS{'OK'}, 0, "request has been deleted, setting computer state to 'available' and exiting");
+		$self->state_exit('', 'available');
 	}
 	
-	if ($computer_type =~ /blade|virtualmachine/) {
-		#Confirm public IP address
-		if ($self->confirm_public_ip_address()) {
-		}
-		
-		# Update the $computer_ip_address varible in case the IP address was different than what was originally in the database
-		#$computer_ip_address = $self->data->get_computer_ip_address();
-		
-		insertloadlog($reservation_id, $computer_id, "info", "node ready adding user account");
-		
-		# Only generate new password if:
-		# ! reinstall
-		# linux and user standalone	
-		if ($request_state_name !~ /^(reinstall)/) {
-			# Create a random password and update the reservation table unless the reservation if for a Linux non-standalone image
-			unless ($image_os_type =~ /linux/ && !$user_standalone) {
-				# Create a random password for the reservation
-				my $reservation_password = getpw();
-				
-				# Update the password in the reservation table
-				if (update_reservation_password($reservation_id, $reservation_password)) {
-					notify($ERRORS{'DEBUG'}, 0, "updated password in the reservation table");
-				}
-				else {
-					$self->reservation_failed("failed to update password in the reservation table", "available");
-				}
-				
-				# Set the password in the DataStructure object
-				$self->data->set_reservation_password($reservation_password);
-			}
-		}
-		
-		# Check if OS module implements a reserve() subroutine
-		if ($self->os->can('reserve')) {
-			# Call the OS module's reserve() subroutine
-			notify($ERRORS{'DEBUG'}, 0, "calling OS module's reserve() subroutine");
-			if ($self->os->reserve()) {
-				notify($ERRORS{'DEBUG'}, 0, "OS module successfully reserved resources for this reservation");
-			}
-			else {
-				$self->reservation_failed("OS module failed to reserve resources for this reservation");
-			}
-		}
-		
-		# Check if this is a parent reservation, only the parent reservation handles notifications
-		if (!$reservation_is_parent) {
-			return 1;
-		}
-		
-		# Assemble the message subject based on whether this is a cluster based or normal request
-		if ($request_forimaging) {
-			$subject = "VCL -- $image_prettyname imaging reservation";
-		}
-		elsif ($reservation_count > 1) {
-			$subject = "VCL -- Cluster-based reservation";
-		}
-		else {
-			$subject = "VCL -- $image_prettyname reservation";
-		}
+	my $mailstring;
+	my $subject;
+	
+	# Assemble the message body reservations
+	if ($request_state_name =~ /^(reinstall)$/) {
+		$subject = "VCL -- $image_prettyname reservation reinstalled";
 		
-		# Assemble the message body reservations
-		if ($request_forimaging) {
-			$mailstring = <<"EOF";
-
-The resources for your VCL image creation request have been successfully reserved.
-
-EOF
-		}
-		elsif ($request_state_name =~ /^(reinstall)$/) {
-			$mailstring = <<"EOF";
-
+		$mailstring = <<"EOF";
 Your reservation was successfully reinstalled and you can proceed to reconnect. 
-Please revisit the Current reservations page for any additional information.
-
+Please revisit the 'Current Reservations' page for any additional information.
 EOF
-		}
-		else {
-			$mailstring = <<"EOF";
-
-The resources for your VCL request have been successfully reserved.
-
-EOF
-		}
-		
-		# Add the image name and IP address information
-		$mailstring .= "Reservation Information:\n";
-		foreach $r (keys %{$request_data->{reservation}}) {
-			my $reservation_image_name = $request_data->{reservation}{$r}{image}{prettyname};
-			$mailstring .= "Image Name: $reservation_image_name\n";
-		}
-		
-		if ($request_state_name !~ /^(reinstall)$/) {
-			$mailstring = <<"EOF";
-
-Connection will not be allowed until you acknowledge using the VCL web interface.  You must acknowledge the reservation within the next 15 minutes or the resources will be reclaimed for other VCL users.
-
-EOF
-		}
+	}
+	else {
+		$subject = "VCL -- $image_prettyname reservation";
 		
-		$mailstring .= <<"EOF";
+		$mailstring = <<"EOF";
+The resources for your VCL reservation have been successfully reserved.
+Connection will not be allowed until you click the 'Connect' button on the 'Current Reservations' page.
+You must acknowledge the reservation within the next 15 minutes or the resources will be reclaimed for other VCL users.
 
 -Visit $user_affiliation_sitewwwaddress
 -Select "Current Reservations"
 -Click the "Connect" button
-
 Upon acknowledgement, all of the remaining connection details will be displayed.
-
 EOF
-		
-		if ($request_forimaging) {
-			$mailstring .= <<"EOF";
-You have up to 8 hours to complete the new image.  Once you have completed preparing the new image:
-
--Visit $user_affiliation_sitewwwaddress
--Select "Current Reservations"
--Click the "Create Image" button and follow the instuctions
-
-EOF
-		} ## end if ($request_forimaging)
-		
-		$mailstring .= <<"EOF";
-Thank You,
-VCL Team
-
-
-******************************************************************
-This is an automated notice. If you need assistance please respond 
-with detailed information on the issue and a help ticket will be 
-generated.
-
-To disable email notices
--Visit $user_affiliation_sitewwwaddress
--Select User Preferences
--Select General Preferences
-
-******************************************************************
-EOF
-		if ($user_emailnotices) {
-			mail($user_email, $subject, $mailstring, $user_affiliation_helpaddress);
-		}
-		else {
-			#just for our email record keeping, might be overkill
-			notify($ERRORS{'MAILMASTERS'}, 0, " $user_email\n$mailstring");
-		}
-		
-		notify($ERRORS{'DEBUG'}, 0, "IMTYPE_name= $user_imtype_name calling notify_via");
-		if ($user_imtype_name ne "none") {
-			notify_via_IM($user_imtype_name, $user_im_id, $mailstring, $user_affiliation_helpaddress);
-		}
-	} ## end if ($computer_type =~ /blade|virtualmachine/)
+	}
 	
-	elsif ($computer_type eq "lab") {
-		if ($image_os_name =~ /sun4x_|rhel/) {
-			# i can't really do anything here
-			# because I need the remoteIP the user
-			# will be accessing the machine from
-			$subject = "VCL -- $image_prettyname reservation";
-			
-			$mailstring = <<"EOF";
-
-A machine with $image_prettyname has been reserved. Use ssh to connect to $computer_ip_address.
-
-Username: your Unity ID
-Password: your Unity password
-
-Connection will not be allowed until you acknowledge using the VCL web interface.
--Visit $user_affiliation_sitewwwaddress
--Select Current Reservations
--Click the Connect button to acknowledge
-
+	$mailstring .= <<"EOF";
 
 Thank You,
 VCL Team
 
-
-
 ******************************************************************
 This is an automated notice. If you need assistance please respond 
 with detailed information on the issue and a help ticket will be 
@@ -1129,35 +993,17 @@ To disable email notices
 
 ******************************************************************
 EOF
-
-			if ($user_emailnotices) {
-				#if  "0" user does not care to get additional notices
-				mail($user_email, $subject, $mailstring, $user_affiliation_helpaddress);
-			}
-			else {
-				#just for our record keeping
-				notify($ERRORS{'MAILMASTERS'}, 0, "$user_email\n$mailstring");
-			}
-			if ($user_imtype_name ne "none") {
-				notify_via_IM($user_imtype_name, $user_im_id, $mailstring, $user_affiliation_helpaddress);
-			}
-		} ## end if ($image_os_name =~ /sun4x_|rhel/)
-		elsif ($image_os_name =~ /realm/) {
-			#same as above
-			return 1;
-		}
-		else {
-			notify($ERRORS{'WARNING'}, 0, "hrmm found an OS I am not set to handle $image_os_name");
-			return 0;
-		}
-	} ## end elsif ($computer_type eq "lab")  [ if ($computer_type =~ /blade|virtualmachine/)
 	
-	#update log table with the IPaddress of the machine
-	if (update_sublog_ipaddress($request_logid, $computer_ip_address)) {
-		notify($ERRORS{'OK'}, 0, "updated sublog $request_logid for node $computer_short_name IPaddress $computer_ip_address");
+	if ($user_emailnotices) {
+		mail($user_email, $subject, $mailstring, $user_affiliation_helpaddress);
 	}
 	else {
-		notify($ERRORS{'WARNING'}, 0, "could not update sublog $request_logid for node $computer_short_name IPaddress $computer_ip_address");
+		# For email record keeping
+		notify($ERRORS{'MAILMASTERS'}, 0, " $user_email\n$mailstring");
+	}
+	
+	if ($user_imtype_name ne "none") {
+		notify_via_IM($user_imtype_name, $user_im_id, $mailstring, $user_affiliation_helpaddress);
 	}
 	
 	return 1;
@@ -1310,55 +1156,6 @@ sub wait_for_child_reservations {
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 confirm_public_ip_address
-
- Parameters  :
- Returns     :
- Description :
-
-=cut
-
-sub confirm_public_ip_address {
-	my $self = shift;
-	
-	my $computer_short_name             = $self->data->get_computer_short_name();
-	my $public_ip_address;
-	my $computer_ip_address             = $self->data->get_computer_ip_address();
-	my $computer_id                     = $self->data->get_computer_id();
-	
-	#Try to get public IP address from OS module
-	if (!$self->os->can("get_public_ip_address")) {
-		notify($ERRORS{'WARNING'}, 0, "unable to retrieve public IP address from $computer_short_name, OS module " . ref($self) . " does not implement a 'get_public_ip_address' subroutine");
-		return;
-	}
-	elsif ($public_ip_address = $self->os->get_public_ip_address()) {
-		notify($ERRORS{'DEBUG'}, 0, "retrieved public IP address from $computer_short_name using the OS module: $public_ip_address");
-		
-		# Update the Datastructure and computer table if the retrieved IP address does not match what is in the database
-		if ($computer_ip_address ne $public_ip_address) {
-			$self->data->set_computer_ip_address($public_ip_address);
-			
-			if (update_computer_address($computer_id, $public_ip_address)) {
-			notify($ERRORS{'OK'}, 0, "updated dynamic public IP address in computer table for $computer_short_name, $public_ip_address");
-			}    
-			else {
-				notify($ERRORS{'WARNING'}, 0, "failed to update dynamic public IP address in computer table for $computer_short_name, $public_ip_address");
-				return 0;
-			}    
-		}
-	}
-	else {
-		notify($ERRORS{'WARNING'}, 0, "failed to retrieve dynamic public IP address from $computer_short_name");
-		#It might not exist or got droppred
-		if (!$self->os->update_public_ip_address()) {
-			$self->reservation_failed("failed to update public IP address");
-		}
-	}
-	return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
 1;
 __END__
 

Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1602979&r1=1602978&r2=1602979&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Mon Jun 16 19:51:54 2014
@@ -1093,6 +1093,9 @@ sub check_time {
 			notify($ERRORS{'DEBUG'}, 0, "reservation will end in 10 minutes or less ($end_diff_minutes)");
 			return "end";
 		}
+		elsif ($request_laststate_name =~ /reserved/) {
+			return "poll";
+		}
 		else {
 			# End time is more than 10 minutes in the future
 			if($serverrequest) {	
@@ -5666,6 +5669,7 @@ sub delete_request {
 
 	# Try to delete any associated entries in the request and reservation tables
 	if (database_execute($sql_request_delete)) {
+		notify($ERRORS{'DEBUG'}, 0, "request deleted: $request_id");
 		return 1;
 	}
 	else {