sub process_connect_methods()

in managementnode/lib/VCL/Module/OS.pm [3753:3891]


sub process_connect_methods {
	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 $reservation_id = $self->data->get_reservation_id();
	my $request_state = $self->data->get_request_state_name();
	my $computer_node_name = $self->data->get_computer_node_name();
	my $nathost_hostname = $self->data->get_nathost_hostname(0);
	my $nathost_public_ip_address = $self->data->get_nathost_public_ip_address(0);
	my $nathost_internal_ip_address = $self->data->get_nathost_internal_ip_address(0);
	
	# Retrieve the connect method info hash
	my $connect_method_info = $self->data->get_connect_methods();
	if (!$connect_method_info) {
		notify($ERRORS{'WARNING'}, 0, "failed to retrieve connect method info");
		return;
	}
	
	my $remote_ip = shift;
	if (!$remote_ip) {
		notify($ERRORS{'OK'}, 0, "reservation remote IP address is not defined, connect methods will be available from any IP address");
		$remote_ip = '0.0.0.0/0';
	}
	elsif ($remote_ip =~ /any/i) {
		notify($ERRORS{'OK'}, 0, "reservation remote IP address is set to ANY, connect methods will be available from any IP address");
		$remote_ip = '0.0.0.0/0';
	}
	else {
		$remote_ip .= "/24";
	}
	
	my $overwrite = shift;
	if (!$overwrite) {
		notify($ERRORS{'DEBUG'}, 0, "overwrite value was not passed as an argument setting to 0");
		$overwrite = 0;
	}
	
	my $computer_ip_address = $self->get_public_ip_address();
	
	CONNECT_METHOD: for my $connect_method_id (sort keys %{$connect_method_info} ) {
		my $connect_method = $connect_method_info->{$connect_method_id};
		
		my $name            = $connect_method->{name};
		my $description     = $connect_method->{description};
		my $service_name    = $connect_method->{servicename};
		my $startup_script  = $connect_method->{startupscript};
		my $install_script  = $connect_method->{installscript};
		my $disabled        = $connect_method->{connectmethodmap}{disabled};
		
		if ($disabled || $request_state =~ /deleted|timeout/) {
			if ($self->service_exists($service_name)) {
				if (!$self->stop_service($service_name)) {
					notify($ERRORS{'WARNING'}, 0, "failed to stop '$service_name' service for '$name' connect method on $computer_node_name");
				}
			}
			
			# Close the firewall ports
			if ($self->can('disable_firewall_port')) {
				for my $connect_method_port_id (keys %{$connect_method->{connectmethodport}}) {
					my $protocol = $connect_method->{connectmethodport}{$connect_method_port_id}{protocol};
					my $port = $connect_method->{connectmethodport}{$connect_method_port_id}{port};
					if (!$self->disable_firewall_port($protocol, $port, $remote_ip, 1)) {
						notify($ERRORS{'WARNING'}, 0, "failed to close firewall port $protocol/$port on $computer_node_name for $remote_ip $name connect method");
						return;
					}
				}
			}
		}
		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) {
				if ($self->service_exists($service_name)) {
					if ($self->start_service($service_name)) {
						$service_started = 1;
					}
					else {
						notify($ERRORS{'WARNING'}, 0, "failed to start '$service_name' service for '$name' connect method on $computer_node_name");
					}
				}
				else {
					notify($ERRORS{'OK'}, 0, "'$service_name' service for '$name' connect method does NOT exist on $computer_node_name, connect method install script is not defined");
				}
			}
			
			# Run the startup script if the service is not started
			if (!$service_started && defined($startup_script)) {
				if (!$self->file_exists($startup_script)) {
					notify($ERRORS{'OK'}, 0, "'$service_name' service startup script for '$name' connect method does not exist on $computer_node_name: $startup_script");
				}
				else {
					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));
					}
				}
			}
			
			for my $connect_method_port_id (keys %{$connect_method->{connectmethodport}}) {
				my $protocol = $connect_method->{connectmethodport}{$connect_method_port_id}{protocol};
				my $port = $connect_method->{connectmethodport}{$connect_method_port_id}{port};
				
				# Open the firewall port
				if ($self->can('enable_firewall_port')) {
					if (!$self->enable_firewall_port($protocol, $port, $remote_ip, 1)) {
						notify($ERRORS{'WARNING'}, 0, "failed to open firewall port $protocol/$port on $computer_node_name for $remote_ip $name connect method");
					}
				}
				
				# Configure NAT port forwarding if NAT is being used
				if ($nathost_hostname) {
					my $nat_public_port = $connect_method->{connectmethodport}{$connect_method_port_id}{natport}{publicport};
					if (!defined($nat_public_port)) {
						notify($ERRORS{'WARNING'}, 0, "$computer_node_name is assigned to NAT host $nathost_hostname but connect method info does not contain NAT port information:\n" . format_data($connect_method));
						return;
					}
					elsif (!$self->nathost_os->firewall->nat_add_port_forward($protocol, $nat_public_port, $computer_ip_address, $port)) {
						notify($ERRORS{'WARNING'}, 0, "failed to configure NAT port forwarding on $nathost_hostname for '$name' connect method: $nathost_public_ip_address:$nat_public_port --> $computer_ip_address:$port ($protocol)");
						return;
					}
				}
			}
		}
	}

	return 1;	
}