From 2f8b4bcb58644714ed59a2e7a5b245d9a2e012e5 Mon Sep 17 00:00:00 2001 From: adam-hampton-sp Date: Tue, 1 Nov 2016 09:52:44 -0500 Subject: [PATCH 1/2] Add support to configure the number of browser processes per instance. Modifies AwsVmManager in the following ways: - CHROME_THREAD_COUNT becomes non-final. - FIREFOX_IE_THREAD_COUNT becomes non final. New values are applied at runtime if the awsProperties contain keys like: - node_max_processes_chrome=8 - node_max_processes_firefox=1 --- .../java/com/rmn/qa/aws/AwsVmManager.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/rmn/qa/aws/AwsVmManager.java b/src/main/java/com/rmn/qa/aws/AwsVmManager.java index ff31b87..9009d83 100644 --- a/src/main/java/com/rmn/qa/aws/AwsVmManager.java +++ b/src/main/java/com/rmn/qa/aws/AwsVmManager.java @@ -66,8 +66,13 @@ public class AwsVmManager implements VmManager { private AmazonEC2Client client; @VisibleForTesting AWSCredentials credentials; private Properties awsProperties; - public static final int CHROME_THREAD_COUNT = 5; - public static final int FIREFOX_IE_THREAD_COUNT = 1; + + // How many chrome browser processes are allowed per EC2 instance. + public static int CHROME_THREAD_COUNT = 5; + + // How many firefox browser processes are allowed per EC2 instance. + public static int FIREFOX_IE_THREAD_COUNT = 1; + private String region; @@ -95,6 +100,33 @@ public AwsVmManager() { client = new AmazonEC2Client(); } AwsVmManager.setRegion(client, awsProperties, region); + + // Allow the user to override the default settings for browser + // processes per EC2 operating system instance. + String maxChromeThreads = awsProperties.getProperty("node_max_processes_chrome"); + if ((null != maxChromeThreads) && (0 != maxChromeThreads.length())) { + int newMaxChromeThreads = Integer.parseInt(maxChromeThreads); + // Sanity check the maximum chrome instances setting. Hard max of 128 sounds good. + if ((newMaxChromeThreads >= 1) && (newMaxChromeThreads <= 128)) { + log.info("Overriding factory default maximum chrome threads with: " + newMaxChromeThreads); + CHROME_THREAD_COUNT = newMaxChromeThreads; + } else { + log.error("Invalid property setting for 'node_max_processes_chrome', ignoring '" + maxChromeThreads + "', using factory default of " + CHROME_THREAD_COUNT); + } + } + + String maxFirefoxThreads = awsProperties.getProperty("node_max_processes_firefox"); + if ((null != maxFirefoxThreads) && (0 != maxFirefoxThreads.length())) { + int newMaxFirefoxThreads = Integer.parseInt(maxFirefoxThreads); + // Sanity check the maximum firefox instances setting. Hard max of 128 sounds good. + if ((newMaxFirefoxThreads >= 1) && (newMaxFirefoxThreads <= 128)) { + log.info("Overriding factory default maximum chrome threads with: " + newMaxFirefoxThreads); + FIREFOX_IE_THREAD_COUNT = newMaxFirefoxThreads; + } else { + log.error("Invalid property setting for 'node_max_processes_firefox', ignoring '" + maxFirefoxThreads + "', using factory default of " + FIREFOX_IE_THREAD_COUNT); + } + } + } public static void setRegion(AmazonEC2Client client, Properties awsProperties, String region) { From c35ffa3cebd5a24313d02668fac87080837cf225 Mon Sep 17 00:00:00 2001 From: adam-hampton-sp Date: Tue, 1 Nov 2016 11:36:42 -0500 Subject: [PATCH 2/2] Add reference shell scripts for Ubuntu Linux based AMIs. --- src/main/resources/grid_start_node.sh | 42 ++++++++++++++++++ src/main/resources/patch_etc_hosts.sh | 62 +++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100755 src/main/resources/grid_start_node.sh create mode 100755 src/main/resources/patch_etc_hosts.sh diff --git a/src/main/resources/grid_start_node.sh b/src/main/resources/grid_start_node.sh new file mode 100755 index 0000000..73224ad --- /dev/null +++ b/src/main/resources/grid_start_node.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# ###################################################################################### +# Shell script to configure a Selenium Grid worker node and add it to the grid. +# This is executed by this command in the crontab, as seen with "cronatab -l": +# @reboot /home/ubuntu/grid/grid_start_node.sh >> /home/ubuntu/grid/process.log 2>&1 +# +# ###################################################################################### +PATH=/sbin:/usr/sbin:/bin:/usr/bin +cd /home/ubuntu/grid/ + +# Call into AWS and figure out what our EC2 instance ID is. +# Sometimes cron kicks off this script before the AWS/EC2 networking stack is awake. +# We need to wait, polling for when the instance ID details beome available. +echo "Grid Automation process started, looking up our EC2 Instance at `date`" +export EC2_INSTANCE_ID= +while [ -z "${EC2_INSTANCE_ID}" ] ; do + # Wait 1 seconds to let the network settle down on boot up and let AWS get all of + # the user-data zip file artifiacts in place. + sleep 1 + export EC2_INSTANCE_ID="`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`" +done + +echo "Retreived our EC2 Instance ID: $EC2_INSTANCE_ID at `date`" + +# Pull down the user data, which will be a zip file containing necessary information +# This is placed in the user-data fild for the instance by the getUserData() and launchNodes() methods. +export NODE_TEMPLATE="/home/ubuntu/grid/nodeConfigTemplate.json" +curl http://169.254.169.254/latest/user-data -o /home/ubuntu/grid/data.zip + +# Now, unzip the data downloaded from the userdata +unzip -o /home/ubuntu/grid/data.zip -d /home/ubuntu/grid/ + +# Replace the instance ID in the node config file +sed "s//$EC2_INSTANCE_ID/g" $NODE_TEMPLATE > /home/ubuntu/grid/nodeConfig.json + +# Finally, run the java process in a window so browsers can run +xvfb-run --auto-servernum --server-args='-screen 0, 1600x1200x24' \ + java -jar /home/ubuntu/grid/selenium-server-node.jar -role node \ + -nodeConfig /home/ubuntu/grid/nodeConfig.json \ + -Dwebdriver.chrome.driver="/home/ubuntu/grid/chromedriver" \ + -log /home/ubuntu/grid/grid.log & + diff --git a/src/main/resources/patch_etc_hosts.sh b/src/main/resources/patch_etc_hosts.sh new file mode 100755 index 0000000..452a7f1 --- /dev/null +++ b/src/main/resources/patch_etc_hosts.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# ########################################################################### +# A shell script to patch the /etc/hosts file for new grid node hosts. +# Stock hosts files on EC2 usually only contain the loopback addresses and +# are missing the actual host name and the DHCP address binding. This can +# delay certain network operations. +# This script patches the /etc/hosts file to contain the hostname on both the +# loopback and DHCP based VPC IP address. +# ########################################################################### +PATH=/sbin:/usr/sbin:/bin:/usr/bin + +# Make certain we can find our host's EC2 instance ID. This ensures that the +# network stack is online and that it can get out to the rest of the netowrk. +export EC2_INSTANCE_ID= +while [ -z "${EC2_INSTANCE_ID}" ] ; do + # Wait 1 seconds to let the network settle down on boot up and let AWS get all of + # the user-data zip file artifiacts in place. + sleep 1 + export EC2_INSTANCE_ID="`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`" +done + +# Now we are certain the network stack is online, what is the host's IP? +LOCALIP=`ifconfig | grep "inet addr" | grep -v "127.0.0" | cut -d':' -f2 | cut -d' ' -f1` +HOSTNAME=`hostname` + +# Count the number of instacnces of the local ip in /etc/hosts. If this comes +# back as zero then we know the local IP address needs to be added to the +# /etc/hosts file. +HASLOCALIP=`grep -c $LOCALIP /etc/hosts` + +# Count the number of instances of the host name in /etc/hosts. If this comes +# back as zero then we know the localhost line needs to be patched to include +# the local host name. +HASHOSTNAME=`grep -c $HOSTNAME /etc/hosts` + +# Add the local hostname to /etc/hosts. +if [ "0" -eq "$HASHOSTNAME" ] ; then + sudo sed -i -e "s/localhost/localhost $HOSTNAME/" /etc/hosts +fi + +# Add the local IP to /etc/hosts. +if [ "0" -eq "$HASLOCALIP" ] ; then + sudo bash -c "echo '# hostname added to support SeleniumGridScaler. ' >> /etc/hosts" + sudo bash -c "echo \"$LOCALIP $HOSTNAME\" >> /etc/hosts" +fi + +# Add an /etc/hosts entry for the Hub IP address. +HASHUBNODEADDR=`grep -c hubHost /home/ubuntu/grid/nodeConfig.json` +while [ "0" -eq "$HASHUBNODEADDR" ] ; do + # Wait for the node setup script to pull down the hub's IP address. + sleep 1 + export HASHUBNODEADDR=`grep -c hubHost /home/ubuntu/grid/nodeConfig.json` +done + +# Lookup the IP address of the hubNode in the nodeConfig.json file. +HUBNODEADDR=`grep hubHost /home/ubuntu/grid/nodeConfig.json | cut -d'"' -f4` + +# Only add the entry if it is actually necessary to do so. +ETCHOSTSHUBCOUNT=`grep -c $HUBNODEADDR /etc/hosts` +if [ "0" -eq "$ETCHOSTSHUBCOUNT" ] ; then + sudo bash -c "echo $HUBNODEADDR hubnode gridhead >> /etc/hosts" +fi