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/12/09 22:11:38 UTC
svn commit: r1644185 [2/2] - in /vcl/trunk/managementnode/lib/VCL: ./
Module/ Module/OS/ Module/OS/Linux/ Module/OS/Linux/firewall/
Module/OS/Linux/init/
Modified: vcl/trunk/managementnode/lib/VCL/new.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/new.pm?rev=1644185&r1=1644184&r2=1644185&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/new.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/new.pm Tue Dec 9 21:11:37 2014
@@ -698,14 +698,14 @@ sub computer_not_being_used {
notify($ERRORS{'WARNING'}, 0, "$computer_short_name is NOT available, its state is $computer_state_name");
return 0;
}
-
+
# Return 0 if computer state is maintenance and request state name is not vmhostinuse
# Allow computers to go from maintenance directly to a vmhost
if ($computer_state_name =~ /^(maintenance)$/ && $request_state_name !~ /tovmhostinuse/) {
notify($ERRORS{'WARNING'}, 0, "$computer_short_name is NOT available, its state is $computer_state_name");
return 0;
}
-
+
# Warn if computer state isn't available or reload - except for reinstall requests
if ($request_state_name !~ /^(reinstall)$/ && $computer_state_name !~ /^(available|reload)$/) {
notify($ERRORS{'WARNING'}, 0, "$computer_short_name state is $computer_state_name, checking if any conflicting reservations are active");
@@ -916,10 +916,10 @@ sub reserve_computer {
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();
-
+
# Needed for computerloadflow
insertloadlog($reservation_id, $computer_id, "addinguser", "Adding user to $computer_short_name");
-
+
# Call OS module's reserve subroutine
if (!$self->os->reserve()) {
$self->reservation_failed("OS module failed to reserve resources for this reservation");
Modified: vcl/trunk/managementnode/lib/VCL/reclaim.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/reclaim.pm?rev=1644185&r1=1644184&r2=1644185&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/reclaim.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/reclaim.pm Tue Dec 9 21:11:37 2014
@@ -106,30 +106,42 @@ sub process {
# Remove related fixedIPsr variable, if it exists
if ($server_request_id) {
- my $variable_name = "fixedIPsr" . $server_request_id;
- if(is_variable_set($variable_name)){
- #Delete from variable table.
- my $delete_sql_statement = "DELETE variable FROM variable WHERE name = '$variable_name' ";
- if (database_execute($delete_sql_statement)) {
- notify($ERRORS{'DEBUG'}, 0, "Deleted server reservation entry for $variable_name from variable table");
- }
- }
+ my $variable_name = "fixedIPsr" . $server_request_id;
+ if (is_variable_set($variable_name)){
+ #Delete from variable table.
+ my $delete_sql_statement = "DELETE variable FROM variable WHERE name = '$variable_name' ";
+ if (database_execute($delete_sql_statement)) {
+ notify($ERRORS{'DEBUG'}, 0, "Deleted server reservation entry for $variable_name from variable table");
+ }
+ }
- if($public_ip_configuration =~ /static/i) {
+ if ($public_ip_configuration =~ /static/i) {
my $original_IPvalue = "originalIPaddr_" . $server_request_id;
- if(is_variable_set($original_IPvalue)) {
+ if (is_variable_set($original_IPvalue)) {
my $original_Public_IP = get_variable($original_IPvalue);
- if(update_computer_public_ip_address($computer_id, $original_Public_IP)) {
+ if (update_computer_public_ip_address($computer_id, $original_Public_IP)) {
notify($ERRORS{'DEBUG'}, 0, "restored original IP address: $original_Public_IP for $computer_state_name ");
}
- my $delete_sql_statement = "DELETE variable FROM variable WHERE name = '$original_IPvalue' ";
- if (database_execute($delete_sql_statement)) {
- notify($ERRORS{'DEBUG'}, 0, "Deleted server reservation entry for $original_IPvalue from variable table");
- }
+ my $delete_sql_statement = "DELETE variable FROM variable WHERE name = '$original_IPvalue' ";
+ if (database_execute($delete_sql_statement)) {
+ notify($ERRORS{'DEBUG'}, 0, "Deleted server reservation entry for $original_IPvalue from variable table");
+ }
}
}
}
-
+
+ # Clean up rules on the NAT host if NAT is used
+ if ($self->nathost_os(0)) {
+ my $nathost_hostname = $self->data->get_nathost_hostname();
+ if ($self->nathost_os->firewall()) {
+ if (!$self->nathost_os->firewall->delete_chain('nat', $reservation_id)) {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to delete '$reservation_id' chain from the nat table on NAT host $nathost_hostname");
+ }
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to delete '$reservation_id' chain from the nat table on NAT host $nathost_hostname, NAT host OS object is not available");
+ }
+ }
# Insert into computerloadlog if request state = timeout
if ($request_state_name =~ /timeout|deleted/) {
Modified: vcl/trunk/managementnode/lib/VCL/utils.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/utils.pm?rev=1644185&r1=1644184&r2=1644185&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/utils.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/utils.pm Tue Dec 9 21:11:37 2014
@@ -126,6 +126,7 @@ our @EXPORT = qw(
get_computer_grp_members
get_computer_ids
get_computer_info
+ get_computer_nathost_info
get_computer_private_ip_address_info
get_computers_controlled_by_mn
get_connect_method_info
@@ -157,6 +158,7 @@ our @EXPORT = qw(
get_management_node_vmhost_ids
get_management_node_vmhost_info
get_module_info
+ get_nathost_assigned_public_ports
get_next_image_default
get_os_info
get_production_imagerevision_info
@@ -203,6 +205,7 @@ our @EXPORT = qw(
notify_via_IM
notify_via_oascript
parent_directory_path
+ populate_reservation_natport
preplogfile
read_file_to_array
remove_array_duplicates
@@ -2974,7 +2977,7 @@ sub database_execute {
=head2 get_request_info
- Parameters : $request_id
+ Parameters : $request_id, $no_cache (optional)
Returns : hash
Description : Retrieves all request/reservation information.
@@ -2982,12 +2985,17 @@ sub database_execute {
sub get_request_info {
- my ($request_id) = @_;
+ my ($request_id, $no_cache) = @_;
if (!(defined($request_id))) {
notify($ERRORS{'WARNING'}, 0, "request ID argument was not specified");
return;
}
+ # Don't use cached info by default
+ if (!defined($no_cache)) {
+ $no_cache = 1;
+ }
+
# Get a hash ref containing the database column names
my $database_table_columns = get_database_table_columns();
@@ -3083,31 +3091,43 @@ EOF
# Add the image info to the hash
my $image_id = $request_info->{reservation}{$reservation_id}{imageid};
- my $image_info = get_image_info($image_id, 1);
+ my $image_info = get_image_info($image_id, $no_cache);
$request_info->{reservation}{$reservation_id}{image} = $image_info;
# Add the imagerevision info to the hash
my $imagerevision_id = $request_info->{reservation}{$reservation_id}{imagerevisionid};
- my $imagerevision_info = get_imagerevision_info($imagerevision_id, 1);
+ my $imagerevision_info = get_imagerevision_info($imagerevision_id, $no_cache);
$request_info->{reservation}{$reservation_id}{imagerevision} = $imagerevision_info;
# Add the computer info to the hash
my $computer_id = $request_info->{reservation}{$reservation_id}{computerid};
- my $computer_info = get_computer_info($computer_id, 1);
+ my $computer_info = get_computer_info($computer_id, $no_cache);
$request_info->{reservation}{$reservation_id}{computer} = $computer_info;
+ # Populate natport table for reservation
+ # Make sure this wasn't called from populate_reservation_natport or else recursive loop will occur
+ my $caller_trace = get_caller_trace(5);
+ if ($caller_trace !~ /populate_reservation_natport/) {
+ my $request_state_name = $request_info->{state}{name};
+ if ($request_state_name =~ /(new|reserved|modified|test)/) {
+ if (!populate_reservation_natport($reservation_id)) {
+ notify($ERRORS{'CRITICAL'}, 0, "failed to populate natport table for reservation");
+ }
+ }
+ }
+
# Add the connect method info to the hash
- my $connect_method_info = get_connect_method_info($imagerevision_id);
+ my $connect_method_info = get_connect_method_info($imagerevision_id, $no_cache);
$request_info->{reservation}{$reservation_id}{connect_methods} = $connect_method_info;
-
+
# Add the managementnode info to the hash
my $management_node_id = $request_info->{reservation}{$reservation_id}{managementnodeid};
- my $management_node_info = get_management_node_info($management_node_id);
+ my $management_node_info = get_management_node_info($management_node_id, $no_cache);
$request_info->{reservation}{$reservation_id}{managementnode} = $management_node_info;
# Retrieve the user info and add to the hash
my $user_id = $request_info->{userid};
- my $user_info = get_user_info($user_id, 0, 1);
+ my $user_info = get_user_info($user_id, 0, $no_cache);
$request_info->{user} = $user_info;
my $imagemeta_root_access = $request_info->{reservation}{$reservation_id}{image}{imagemeta}{rootaccess};
@@ -3899,7 +3919,7 @@ EOF
$vmhost_info->{vmprofile}{vmpath} = $vmhost_info->{vmprofile}{datastorepath} if !$vmhost_info->{vmprofile}{vmpath};
$vmhost_info->{vmprofile}{virtualdiskpath} = $vmhost_info->{vmprofile}{vmpath} if !$vmhost_info->{vmprofile}{virtualdiskpath};
-
+
notify($ERRORS{'DEBUG'}, 0, "retrieved VM host $vmhost_id info, computer: $vmhost_info->{computer}{hostname}");
$ENV{vmhost_info}{$vmhost_id} = $vmhost_info;
return $ENV{vmhost_info}{$vmhost_id};
@@ -6882,8 +6902,11 @@ sub get_computer_info {
notify($ERRORS{'WARNING'}, 0, "computer identifier argument was not supplied");
return;
}
-
- return $ENV{computer_info}{$computer_identifier} if (!$no_cache && $ENV{computer_info}{$computer_identifier});
+
+ if (!$no_cache && defined($ENV{computer_info}{$computer_identifier})) {
+ return $ENV{computer_info}{$computer_identifier};
+ }
+ notify($ERRORS{'DEBUG'}, 0, "retrieving info for computer $computer_identifier");
# Get a hash ref containing the database column names
my $database_table_columns = get_database_table_columns();
@@ -6895,7 +6918,6 @@ sub get_computer_info {
'module',
'schedule',
'platform',
- 'nathost',
);
# Construct the select statement
@@ -6935,10 +6957,6 @@ ON (
)
LEFT JOIN (schedule) ON (schedule.id = computer.scheduleid)
LEFT JOIN (module AS predictivemodule) ON (predictivemodule.id = computer.predictivemoduleid)
-LEFT JOIN (nathost, nathostcomputermap) ON (
- nathostcomputermap.computerid = computer.id
- AND nathostcomputermap.nathostid = nathost.id
-)
WHERE
computer.deleted != '1'
@@ -6996,6 +7014,8 @@ EOF
}
}
+ my $computer_id = $computer_info->{id};
+
# Set the short name of the computer based on the hostname
my $computer_hostname = $computer_info->{hostname};
my ($computer_shortname) = $computer_hostname =~ /^([^\.]+)/;
@@ -7054,7 +7074,12 @@ EOF
}
}
- #notify($ERRORS{'DEBUG'}, 0, "retrieved info for computer '$computer_identifier':\n" . format_data($computer_info));
+ my $nathost_info = get_computer_nathost_info($computer_id, $no_cache);
+ if ($nathost_info) {
+ $computer_info->{nathost} = $nathost_info;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "retrieved info for computer: $computer_identifier");
$ENV{computer_info}{$computer_identifier} = $computer_info;
$ENV{computer_info}{$computer_identifier}{RETRIEVAL_TIME} = time;
return $ENV{computer_info}{$computer_identifier};
@@ -7062,6 +7087,456 @@ EOF
#/////////////////////////////////////////////////////////////////////////////
+=head2 get_computer_nathost_info
+
+ Parameters : $computer_identifier
+ Returns : hash reference
+ Description : Retrieves nathost info if a nathost is mapped to the computer via
+ the nathostcomputermap table. Example:
+ {
+ "HOSTNAME" => "nat1.vcl.org",
+ "datedeleted" => undef,
+ "deleted" => 0,
+ "id" => 2,
+ "natIP" => "x.x.x.x",
+ "nathostcomputermap" => {
+ "computerid" => 3591,
+ "nathostid" => 2
+ },
+ "resource" => {
+ "id" => 6185,
+ "resourcetype" => {
+ "id" => 16,
+ "name" => "managementnode"
+ },
+ "resourcetypeid" => 16,
+ "subid" => 8
+ },
+ "resourceid" => 6185
+ }
+
+=cut
+
+sub get_computer_nathost_info {
+ my ($computer_identifier, $no_cache) = @_;
+ if (!defined($computer_identifier)){
+ notify($ERRORS{'WARNING'}, 0, "computer identifier argument was not supplied");
+ return;
+ }
+
+ return $ENV{nathost_info}{$computer_identifier} if (!$no_cache && $ENV{nathost_info}{$computer_identifier});
+
+ # Get a hash ref containing the database column names
+ my $database_table_columns = get_database_table_columns();
+
+ my @tables = (
+ 'nathost',
+ 'nathostcomputermap',
+ 'resource',
+ 'resourcetype',
+ );
+
+ # 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
+computer,
+nathostcomputermap,
+nathost,
+resource,
+resourcetype
+
+WHERE
+nathostcomputermap.computerid = computer.id
+AND nathostcomputermap.nathostid = nathost.id
+AND nathost.resourceid = resource.id
+AND resource.resourcetypeid = resourcetype.id
+AND
+EOF
+
+ # If the computer identifier is all digits match it to computer.id
+ # Otherwise, match computer.hostname
+ if ($computer_identifier =~ /^\d+$/) {
+ $select_statement .= "computer.id = \'$computer_identifier\'";
+ }
+ else {
+ $select_statement .= "computer.hostname REGEXP '$computer_identifier(\\\\.|\$)'";
+ }
+
+ # Call the database select subroutine
+ my @selected_rows = database_select($select_statement);
+
+ if (!@selected_rows) {
+ notify($ERRORS{'DEBUG'}, 0, "NAT host is not mapped to computer $computer_identifier");
+ return {};
+ }
+ elsif (scalar @selected_rows > 1) {
+ notify($ERRORS{'WARNING'}, 0, "unable to determine NAT host mapped to computer $computer_identifier, " . scalar @selected_rows . " rows were returned from database select statement:\n$select_statement");
+ return;
+ }
+
+ # Get the single row returned from the select statement
+ my $row = $selected_rows[0];
+
+ # Construct a hash with all of the computer info
+ my $nathost_info;
+
+ # Loop through all the columns returned
+ for my $key (keys %$row) {
+ 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]) {
+ $nathost_info->{$column} = $value;
+ }
+ elsif ($table eq 'resourcetype') {
+ $nathost_info->{resource}{resourcetype}{$column} = $value;
+ }
+ else {
+ $nathost_info->{$table}{$column} = $value;
+ }
+ }
+
+ $nathost_info->{HOSTNAME} = '<unknown>';
+
+ my $resource_id = $nathost_info->{resource}{id};
+ my $resource_type = $nathost_info->{resource}{resourcetype}{name};
+ my $resource_subid = $nathost_info->{resource}{subid};
+ if ($resource_type eq 'managementnode') {
+ my $management_node_info = get_management_node_info($resource_subid) || {};
+ $nathost_info->{HOSTNAME} = $management_node_info->{hostname};
+ }
+ elsif ($resource_type eq 'computer') {
+ my $computer_info = get_computer_info($resource_subid) || {};
+ $nathost_info->{HOSTNAME} = $computer_info->{hostname};
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "NAT host resource type is not supported: $resource_type, resource ID: $resource_id");
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "retrieved info for NAT host mapped to computer computer $computer_identifier:\n" . format_data($nathost_info));
+ $ENV{nathost_info}{$computer_identifier} = $nathost_info;
+ return $ENV{nathost_info}{$computer_identifier};
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_nathost_assigned_public_ports
+
+ Parameters : $nathost_id
+ Returns : array
+ Description : Retrieves a list of natport.publicport values for the nathost
+ specified by the argument.
+
+=cut
+
+sub get_nathost_assigned_public_ports {
+ my ($nathost_id) = @_;
+ if (!defined($nathost_id)) {
+ notify($ERRORS{'WARNING'}, 0, "nathost ID argument was not supplied");
+ return;
+ }
+
+ my $select_statement = "SELECT publicport FROM natport WHERE nathostid = $nathost_id ORDER BY publicport ASC";
+ my @selected_rows = database_select($select_statement);
+ my @ports;
+ for my $row (@selected_rows) {
+ push @ports, $row->{publicport};
+ }
+
+ if (@ports) {
+ notify($ERRORS{'DEBUG'}, 0, "retrieved assigned public ports for nathost $nathost_id: " . join(", ", @ports));
+ }
+ else {
+ notify($ERRORS{'DEBUG'}, 0, "no public ports are assigned for nathost $nathost_id");
+ }
+ return @ports;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 populate_reservation_natport
+
+ Parameters : $reservation_id
+ Returns : boolean
+ Description : Populates the natport table for a reservation if the computer is
+ mapped to a nathost. The natport table is checked for each
+ connect method port assigned to each connect method for the
+ reservation.
+
+=cut
+
+sub populate_reservation_natport {
+ my ($reservation_id) = @_;
+ if (!defined($reservation_id)) {
+ notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not supplied");
+ return;
+ }
+
+ my $request_info = {get_reservation_request_info($reservation_id, 0)};
+ my $computer_id = $request_info->{reservation}{$reservation_id}{computerid};
+ my $computer_name = $request_info->{reservation}{$reservation_id}{computer}{SHORTNAME};
+ my $imagerevision_id = $request_info->{reservation}{$reservation_id}{imagerevision}{id};
+
+ my $nathost_info = $request_info->{reservation}{$reservation_id}{computer}{nathost};
+ my $nathost_id = $nathost_info->{id};
+ my $nathost_hostname = $nathost_info->{HOSTNAME};
+ my $nathost_public_ip_address = $nathost_info->{natIP};
+
+ # Make sure the nathost info is defined
+ if (!defined($nathost_id)) {
+ notify($ERRORS{'DEBUG'}, 0, "natport table does not need to be populated, computer $computer_id is not mapped to a NAT host");
+ return 1;
+ }
+ notify($ERRORS{'DEBUG'}, 0, "computer $computer_id is mapped to NAT host $nathost_hostname ($nathost_hostname)");
+
+ # Retrieve the connect method info - do not use cached info
+ my $connect_method_info = get_connect_method_info($imagerevision_id, 1);
+
+ # Retrieve the ports already assigned to the nathost
+ my @assigned_ports = get_nathost_assigned_public_ports($nathost_id);
+
+ # Put the assigned ports into a hash for easy checking
+ my %assigned_port_hash = map { $_ => 1 } @assigned_ports;
+
+ my %available_port_hash;
+
+ # Retrieve and parse the natport_ranges variable
+ my $natport_ranges_variable = get_variable('natport_ranges') || '49152-65535';
+ my @natport_ranges = split(/[,;]+/, $natport_ranges_variable);
+ for my $natport_range (@natport_ranges) {
+ my ($start_port, $end_port) = $natport_range =~ /(\d+)-(\d+)/g;
+ if (!defined($start_port)) {
+ notify($ERRORS{'WARNING'}, 0, "unable to parse NAT port range: '$natport_range'");
+ next;
+ }
+
+ # Make sure port range isn't backwards
+ if ($end_port < $start_port) {
+ my $start_port_temp = $start_port;
+ $start_port = $end_port;
+ $end_port = $start_port_temp;
+ }
+
+ # Loop through all of the ports in the range, check if already assigned
+ for (my $port = $start_port; $port<=$end_port; $port++) {
+ if (!defined($assigned_port_hash{$port})) {
+ $available_port_hash{$port} = 1;
+ }
+ }
+ }
+
+ # Loop through the connect methods
+ # Check if a public port has been assigned for each
+ for my $connect_method_id (sort keys %$connect_method_info) {
+ my $connect_method_port_info = $connect_method_info->{$connect_method_id}{connectmethodport};
+
+ CONNECT_METHOD_PORT_ID: for my $connect_method_port_id (sort keys %$connect_method_port_info) {
+ my $connect_method_port = $connect_method_port_info->{$connect_method_port_id};
+
+ if (defined($connect_method_port->{natport})) {
+ notify($ERRORS{'DEBUG'}, 0, "NAT public port is already assigned for connect method ID: $connect_method_id, port ID: $connect_method_port_id\n" . format_data($connect_method_port->{natport}));
+ next CONNECT_METHOD_PORT_ID;
+ }
+
+ # Select a random port from the list of available ports
+ my @available_ports = sort keys %available_port_hash;
+ my $available_port_count = scalar(@available_ports);
+ if (!$available_port_count) {
+ notify($ERRORS{'CRITICAL'}, 0, "no NAT public ports are available for NAT host $nathost_hostname ($nathost_id)");
+ return;
+ }
+ my $random_index = int(rand($available_port_count));
+ my $public_port = $available_ports[$random_index];
+
+ # Remove the selected port from the available port hash
+ delete $available_port_hash{$public_port};
+
+ # Make multiple attempts, it's possible 2 reservations will attempt to assign the same public port at the same time
+ # Using random ports helps avoid collisions
+ # TODO: add semaphore
+ my $attempt_limit = 5;
+ for (my $attempt = 1; $attempt <= $attempt_limit; $attempt++) {
+ sleep_uninterrupted(1);
+ if (insert_natport($reservation_id, $nathost_id, $connect_method_port_id, $public_port)) {
+ next CONNECT_METHOD_PORT_ID;
+ }
+ }
+ notify($ERRORS{'CRITICAL'}, 0, "failed to insert natport entry after making $attempt_limit attempts:\n" .
+ "connectmethod ID: $connect_method_id\n" .
+ "connectmethodport ID: $connect_method_port_id\n" .
+ "reservation ID: $reservation_id\n" .
+ "nathost ID: $nathost_id\n" .
+ "public port: $public_port"
+ );
+ return;
+ }
+ }
+
+ # Get the connect method info again to verify all ports are assigned a NAT public port
+ my $info_string = "";
+ $connect_method_info = get_connect_method_info($imagerevision_id, 1);
+ for my $connect_method_id (sort keys %$connect_method_info) {
+ my $connect_method = $connect_method_info->{$connect_method_id};
+ my $connect_method_name = $connect_method->{name};
+
+ for my $connect_method_port_id (sort keys %{$connect_method->{connectmethodport}}) {
+ my $connect_method_port = $connect_method->{connectmethodport}{$connect_method_port_id};
+ my $protocol = $connect_method_port->{protocol};
+ my $port = $connect_method_port->{port};
+
+ my $nat_port = $connect_method_port->{natport};
+ my $public_port = $nat_port->{publicport};
+ if (!defined($nat_port)) {
+ notify($ERRORS{'WARNING'}, 0, "NAT public port is not assigned for connect method ID: $connect_method_id, port ID: $connect_method_port_id");
+ return;
+ }
+ $info_string .= "$connect_method_name: $nathost_public_ip_address:$public_port --> $computer_name:$port ($protocol)\n";
+ }
+ }
+ notify($ERRORS{'DEBUG'}, 0, "NAT port forwarding information:\n$info_string");
+ return 1;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 insert_natport
+
+ Parameters : $reservation_id, $nathost_id, $connect_method_port_id, $public_port
+ Returns : boolean
+ Description : Inserts an entry into the natport table.
+
+=cut
+
+sub insert_natport {
+ my ($reservation_id, $nathost_id, $connect_method_port_id, $public_port) = @_;
+ if (!defined($reservation_id)) {
+ notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not supplied");
+ return;
+ }
+ elsif (!defined($nathost_id)) {
+ notify($ERRORS{'WARNING'}, 0, "nathost ID argument was not supplied");
+ return;
+ }
+ elsif (!defined($connect_method_port_id)) {
+ notify($ERRORS{'WARNING'}, 0, "connect method port ID argument was not supplied");
+ return;
+ }
+ elsif (!defined($public_port)) {
+ notify($ERRORS{'WARNING'}, 0, "public port argument was not supplied");
+ return;
+ }
+
+ my $insert_statement = <<EOF;
+INSERT INTO
+natport
+(
+ reservationid,
+ nathostid,
+ connectmethodportid,
+ publicport
+)
+VALUES
+(
+ $reservation_id,
+ $nathost_id,
+ $connect_method_port_id,
+ $public_port
+)
+EOF
+
+ my $result = database_execute($insert_statement);
+ if ($result) {
+ notify($ERRORS{'DEBUG'}, 0, "inserted entry into natport table:\nreservation: $reservation_id\nnathost ID: $nathost_id\nconnectmethodport ID: $connect_method_port_id\npublic port: $public_port");
+ return 1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to insert entry into natport table\nreservation: $reservation_id\nnathost ID: $nathost_id\nconnectmethodport ID: $connect_method_port_id\npublic port: $public_port");
+ return 0;
+ }
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_reservation_request_id
+
+ Parameters : $reservation_id, $no_cache (optional)
+ Returns : integer
+ Description : Retrieves the request ID assigned of a reservation.
+
+=cut
+
+sub get_reservation_request_id {
+ my ($reservation_id, $no_cache) = @_;
+ if (!defined($reservation_id)) {
+ notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not supplied");
+ return;
+ }
+
+ if (!$no_cache && defined($ENV{reservation_request_id}{$reservation_id})) {
+ return $ENV{reservation_request_id}{$reservation_id};
+ }
+
+ my $select_statement = "SELECT requestid FROM reservation WHERE id = '$reservation_id'";
+ my @selected_rows = database_select($select_statement);
+ if (!@selected_rows) {
+ notify($ERRORS{'WARNING'}, 0, "failed to retrieve request ID for reservation $reservation_id");
+ return;
+ }
+
+ my $row = $selected_rows[0];
+ my $request_id = $row->{requestid};
+ notify($ERRORS{'DEBUG'}, 0, "retrieved reservation $reservation_id request ID: $request_id");
+ $ENV{reservation_request_id}{$reservation_id} = $request_id;
+ return $request_id;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_reservation_request_info
+
+ Parameters : $reservation_id, $no_cache (optional)
+ Returns : hash reference
+ Description : Retrieves the request info for a reservation.
+
+=cut
+
+sub get_reservation_request_info {
+ my ($reservation_id, $no_cache) = @_;
+ if (!defined($reservation_id)) {
+ notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not supplied");
+ return;
+ }
+
+ my $request_id = get_reservation_request_id($reservation_id, $no_cache);
+ if (!$request_id) {
+ notify($ERRORS{'WARNING'}, 0, "unable to retrieve request info for reservation $reservation_id, failed to determine request ID for reservation");
+ return;
+ }
+
+ return get_request_info($request_id, $no_cache);
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 get_computer_ids
Parameters : $computer_identifier
@@ -7897,11 +8372,15 @@ sub reservation_being_processed {
sub run_command {
my ($command, $no_output) = @_;
- my $output_string = `$command 2>&1`;
+ my $output_string;
+ $output_string = `$command 2>&1`;
+ $output_string = '' unless $output_string;
+
my $exit_status = $?;
if ($exit_status >= 0) {
$exit_status = $exit_status >> 8;
}
+
# Remove any trailing newlines from the output
chomp $output_string;
@@ -9611,7 +10090,52 @@ sub kill_child_processes {
Parameters : $imagerevision_id, $no_cache (optional)
Returns : hash reference
Description : Returns the connect methods for the image revision specified as
- the argument.
+ the argument. Example:
+ {
+ 4 => {
+ "RETRIEVAL_TIME" => "1417709281",
+ "connectmethodmap" => {
+ "OSid" => 36,
+ "OStypeid" => undef,
+ "autoprovisioned" => undef,
+ "connectmethodid" => 4,
+ "disabled" => 0,
+ "imagerevisionid" => undef
+ },
+ "connectmethodport" => {
+ 35 => {
+ "connectmethodid" => 4,
+ "id" => 35,
+ "natport" => {
+ "connectmethodportid" => 35,
+ "nathostid" => 2,
+ "publicport" => 56305,
+ "reservationid" => 3115
+ },
+ "port" => 3389,
+ "protocol" => "TCP"
+ },
+ 37 => {
+ "connectmethodid" => 4,
+ "id" => 37,
+ "natport" => {
+ "connectmethodportid" => 37,
+ "nathostid" => 2,
+ "publicport" => 63058,
+ "reservationid" => 3115
+ },
+ "port" => 3389,
+ "protocol" => "UDP"
+ }
+ },
+ "description" => "Linux xRDP (Remote Desktop Protocol)",
+ "id" => 4,
+ "name" => "xRDP",
+ "servicename" => "xrdp",
+ "startupscript" => undef
+ }
+ }
+
=cut
@@ -9646,6 +10170,7 @@ sub get_connect_method_info {
'connectmethod',
'connectmethodport',
'connectmethodmap',
+ 'natport',
);
# Construct the select statement
@@ -9666,10 +10191,13 @@ sub get_connect_method_info {
$select_statement .= <<EOF;
FROM
connectmethod,
-connectmethodport,
+
+connectmethodport
+LEFT JOIN natport ON (natport.connectmethodportid = connectmethodport.id),
+
connectmethodmap,
-imagerevision
+imagerevision
LEFT JOIN image ON (image.id = imagerevision.imageid)
LEFT JOIN OS ON (OS.id = image.OSid)
LEFT JOIN OStype ON (OStype.name = OS.type)
@@ -9712,15 +10240,18 @@ EOF
# 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 'connectmethod') {
$connect_method_info->{$connectmethod_id}{$column} = $value;
}
elsif ($table eq 'connectmethodport') {
- my $protocol = $row->{"connectmethodport-protocol"};
- my $port = $row->{"connectmethodport-port"};
- $connect_method_info->{$connectmethod_id}{$table}{$protocol}{$port} = 1;
+ my $connectmethodport_id = $row->{"connectmethodport-id"};
+ $connect_method_info->{$connectmethod_id}{'connectmethodport'}{$connectmethodport_id}{$column} = $value;
+ }
+ elsif ($table eq 'natport') {
+ if (defined($value)) {
+ my $connectmethodport_id = $row->{"connectmethodport-id"};
+ $connect_method_info->{$connectmethod_id}{'connectmethodport'}{$connectmethodport_id}{'natport'}{$column} = $value;
+ }
}
else {
$connect_method_info->{$connectmethod_id}{$table}{$column} = $value;
@@ -11932,7 +12463,6 @@ EOF
=cut
-
sub get_provisioning_osinstalltype_info {
my ($provisioning_id) = @_;
if (!defined($provisioning_id)) {