sub execute()

in managementnode/lib/VCL/Module/OS.pm [3174:3300]


sub execute {
	my @original_arguments = @_;
	my ($argument) = @_;
	my ($computer_name, $command, $display_output, $timeout_seconds, $max_attempts, $port, $user, $password, $identity_key, $ignore_error);
	
	my $self;
	
	# Check if this subroutine was called as an object method
	if (ref($argument) && ref($argument) =~ /VCL::Module/) {
		# Subroutine was called as an object method ($self->execute)
		$self = shift;
		($argument) = @_;
		
		#notify($ERRORS{'DEBUG'}, 0, "called as an object method: " . ref($self));
		
		# Get the computer name from the reservation data
		$computer_name = $self->data->get_computer_node_name();
		if (!$computer_name) {
			notify($ERRORS{'WARNING'}, 0, "called as an object method, failed to retrieve computer name from reservation data");
			return;
		}
		#notify($ERRORS{'DEBUG'}, 0, "retrieved computer name from reservation data: $computer_name");
	}
	
	my $no_persistent_connection = 0;
	
	# Check the argument type
	if (ref($argument)) {
		if (ref($argument) eq 'HASH') {
			#notify($ERRORS{'DEBUG'}, 0, "first argument is a hash reference:\n" . format_data($argument));
			
			$computer_name = $argument->{node} if (!$computer_name);
			$command = $argument->{command};
			$display_output = $argument->{display_output};
			$timeout_seconds = $argument->{timeout_seconds};
			$max_attempts = $argument->{max_attempts};
			$port = $argument->{port};
			$user = $argument->{user};
			$password = $argument->{password};
			$identity_key = $argument->{identity_key};
			$ignore_error = $argument->{ignore_error};
			$no_persistent_connection = $argument->{no_persistent_connection};
		}
		else {
			notify($ERRORS{'WARNING'}, 0, "invalid argument reference type passed: " . ref($argument) . ", if a reference is passed as the argument it may only be a hash or VCL::Module reference");
			return;
		}
	}
	else {
		# Argument is not a reference, computer name must be the first argument unless this subroutine was called as an object method
		# If called as an object method, $computer_name will already be populated
		if (!$computer_name) {
			$computer_name = shift;
			#notify($ERRORS{'DEBUG'}, 0, "first argument is a scalar, should be the computer name: $computer_name, remaining arguments:\n" . format_data(\@_));
		}
		else {
			#notify($ERRORS{'DEBUG'}, 0, "first argument should be the command:\n" . format_data(\@_));
		}
		
		# Get the remaining arguments
		($command, $display_output, $timeout_seconds, $max_attempts, $port, $user, $password, $identity_key, $ignore_error) = @_;
	}
	
	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;
	}
	
	# TESTING: use the new subroutine if $ENV{execute_new} is set and the command isn't one that's known to fail with the new subroutine
	if ($ENV->{execute_new} && !$no_persistent_connection) {
		my @excluded_commands = $command =~ /(vmkfstools|qemu-img|Convert-VHD|scp|shutdown|reboot)/i;
		if (@excluded_commands) {
			notify($ERRORS{'DEBUG'}, 0, "not using execute_new, command: $command\nexcluded commands matched:\n" . join("\n", @excluded_commands));
		}
		else {
			return execute_new(@original_arguments);
		}
	}
	
	# If 'ssh_user' key is set in this object, use it
	# This allows OS modules to specify the username to use
	if ($self && $self->{ssh_user}) {
		#notify($ERRORS{'DEBUG'}, 0, "\$self->{ssh_user} is defined: $self->{ssh_user}");
		$user = $self->{ssh_user};
	}
	elsif (!$port) {
		$user = 'root';
	}
	
	# If 'ssh_port' key is set in this object, use it
	# This allows OS modules to specify the port to use
	if ($self && $self->{ssh_port}) {
		#notify($ERRORS{'DEBUG'}, 0, "\$self->{ssh_port} is defined: $self->{ssh_port}");
		$port = $self->{ssh_port};
	}
	elsif (!$port) {
		$port = 22;
	}
	
	my $arguments = {
		node => $computer_name,
		command => $command,
		identity_paths => $identity_key,
		user => $user,
		port => $port,
		output_level => $display_output,
		max_attempts => $max_attempts,
		timeout_seconds => $timeout_seconds,
	};
	
	# Run the command via SSH
	my ($exit_status, $output) = run_ssh_command($arguments);
	if (defined($exit_status) && defined($output)) {
		if ($display_output) {
			notify($ERRORS{'DEBUG'}, 0, "executed command: '$command', exit status: $exit_status, output:\n" . join("\n", @$output));
		}
		return ($exit_status, $output);
	}
	else {
		notify($ERRORS{'WARNING'}, 0, "failed to run command on $computer_name: $command") if $display_output;
		return;
	}
}