Unique usernames for BPM scripts

powerconnect for splunk

Imagine that you have created a BPM script that monitors one of your critical business systems from 10 locations around the world. The application only allows users to log on once, so you must find a way to have each location use a different login account for the application.

Unfortunately the most obvious solution (creating a file-based parameter and setting the "username" field to "Select next row: Unique") does not work for BPM scripts, only with LoadRunner.

There are a few different solutions to this problem, each with their own tradeoffs.

You could just create 10 copies of the same script, each with a different password, but this quickly becomes painful when you find that you need to update the script and have to manually check out and re-upload 10 scripts.

Or you could write some code that used a different login, based on a lookup of the hostname of the computer is was running from:

	// Select username/password based on the hostname that the BPM script is running from.
	if (strcmp("bpm-aus-mel01", lr_get_host_name()) == 0) {
		lr_save_string("bpmuser1", "Username");
		lr_save_string("Welcome1", "Password");
	} else if (strcmp("bpm-aus-syd01", lr_get_host_name()) == 0) {
		lr_save_string("bpmuser2", "Username");
		lr_save_string("Welcome1", "Password");
	} else if (strcmp("bpm-aus-can01", lr_get_host_name()) == 0) {
		lr_save_string("bpmuser3", "Username");
		lr_save_string("Welcome1", "Password");
	} else if (strcmp("bpm-aus-bris01", lr_get_host_name()) == 0) {
		lr_save_string("bpmuser4", "Username");
		lr_save_string("Welcome1", "Password");
	} else if (strcmp("bpm-aus-per01", lr_get_host_name()) == 0) {
		lr_save_string("bpmuser5", "Username");
		lr_save_string("Welcome1", "Password");
	} else {
		lr_error_message("Could not find username for host: %s", lr_get_host_name());
	}

Some people are naturally resistant to this approach because they can see that, while they now only have to maintain a single script, all the values are hardcoded so they have to make a code change if they want to move the script to a different BPM.

It is natural for someone who understands programming to want to separate code from data because that generally makes for a more maintainable solution. In this case, putting this data into file-based parameters doesn't save you any maintenance effort as any change still requires you to check the script out, make the change, and then re-upload. Here is the code anyway:

/*
This function gets a {Username} and {Password} based on the hostname of the computer is is running from.

Put your call to this function inside your login transaction, so that it will be marked as failed and 
you will be alerted if a username cannot be found for the host that the script is running from.

Set up your parameter file with the following columns:
* Username (Select next row: Sequential, Update value on: Once)
* Password (Select next row: Same line as Username)
* Hostname (Select next row: Same line as Username)
The last row in the parameter file should have "LAST" in all columns.

e.g.

Username,Password,Hostname
user1,password1,hostname1
user2,password2,hostname2
user3,password3,hostname3
user4,password4,hostname4
LAST,LAST,LAST

*/
void jds_get_username_by_host(void) {
	int i;

	for (i=0; i<100; i++) {
		// Check if we have reached the last row in the data file
		if (strcmp(lr_eval_string("{Username}"), "LAST") == 0) {
			lr_error_message("Cannot find a user account for hostname: %s. Check your data file.", lr_get_host_name());
			lr_exit(LR_EXIT_VUSER, LR_FAIL); // Note that vuser_end will still be run before the script exits.
		} else if (strcmp(lr_eval_string("{Hostname}"), lr_get_host_name()) == 0) {
			lr_output_message("Found username: %s for host: %s", lr_eval_string("{Username}"), lr_get_host_name());
			return;
		}
		lr_advance_param("Username");
	}

	// If we reach the end of the for loop, it means that we have checked 100 rows without finding a value.
	// As the lr_advance_param starts at the beginning of the file again when it has reached the end, we 
	// abort the script here or we will be stuck in a loop forever.
	lr_error_message("Cannot find a user account for hostname: %s. Check your data file.", lr_get_host_name());
	lr_exit(LR_EXIT_VUSER, LR_FAIL); // Note that vuser_end will still be run before the script exits.
}

In this case, the main advantage of putting the username and password in a parameter file, instead of hardcoding it, is that VuGen will do syntax highlighting for the parameter names when they appear in the script.

Tech tips from JDS