Selenium Monitor

From OpenNMS
Jump to navigation Jump to search

This Monitor is Deprecated

While this monitor can (probably) be made to work, it is deprecated and probably shouldn't be used.

The idea was that one could take the Selenium IDE, record a session and then export that to a JUnit test. Then that output would be minimally modified and added to OpenNMS so that it could periodically run the test.

The main issue is that the raw Selenium test *requires* Firefox, and Firefox requires an entire graphics stack, i.e. Xorg. Most servers don't have that for a number of good reasons, and if you are trying to run Selenium tests on a large number of sites the memory resources could become prohibitive.

An attempt to fix this was made using PhantomJS, another Javascript library that did not require a graphical interface. Unfortunately, it is no longer being maintained since March of 2018, and some of the outstanding issues include using excessive memory.

We've made a note of this with an internal OpenNMS issue.

Moving forward the option looks like to use "headless Chrome" but neither OpenNMS nor Selenium support that at the moment.

We still have the Page Sequence Monitor. This is very efficient but can be difficult to set up.


Tested for Versions
The instructions in this article have been tested against the following versions of OpenNMS.
Tested Against:
Version 19.0.1 tested by Fuhrmann
Version 19.1.0 tested by Fuhrmann

Selenium Monitor Specification

The SeleniumMonitor similar to the PageSequenceMonitor was created to handle tracking sequences on websites that rely heavily on Javascript within the site. The monitor uses the Selenium API to run regression testing through the browser on the supplied URL.


Overview

The SeleniumMonitor uses Selenium under the covers to test websites. You can use the Selenium IDE in Firefox, which is an add-on, to create your sequence. Once you have a working test running in the Selenium IDE you can export your test as a JUnit 4 (Webdriver) and with a few changes to the file can run that in OpenNMS.

Create Selenium Test

LoginTest sequence example

As we said above you have to create a working Selenium sequence. We will use the demo website of our Zabbix friends to give an example. The sequence uses the guest login, switches to the problem page and acknowledges all current alarm adding the comment "OpenNMS Selenium Test :-)".

So download the add-on for Firefox and create your sequence. When it's working, export the test case as JAVA / JUnit4 / Webdriver file using the extention .groovy. eg. LoginTest.groovy.

Groovy File Modifications

The exported Groovy file should similar to this one:

package com.example.tests;

import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;

public class LoginTest {
  private WebDriver driver;
  private String baseUrl;
  private boolean acceptNextAlert = true;
  private StringBuffer verificationErrors = new StringBuffer();

  @Before
  public void setUp() throws Exception {
    driver = new FirefoxDriver();
    baseUrl = "https://zabbix.org/zabbix/";
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
  }

  @Test
  public void testLogin() throws Exception {
    driver.get(baseUrl + "/zabbix/");
    driver.findElement(By.linkText("sign in as guest")).click();
    driver.findElement(By.linkText("Problems")).click();
    driver.findElement(By.id("all_eventids")).click();
    driver.findElement(By.cssSelector("button[name=\"action\"]")).click();
    driver.findElement(By.id("message")).clear();
    driver.findElement(By.id("message")).sendKeys("OpenNMS Selenium Test :-)");
    driver.findElement(By.id("acknowledge_type_1")).click();
    driver.findElement(By.name("action")).click();
    driver.findElement(By.cssSelector("a.top-nav-signout")).click();
  }...


OpenNMS SeleniumPoller

To make your Selenium testcase runnable by the OpenNMS SeleniumMonitor follow the next steps.

Changing the Package

At the top of the groovy class change the package to

package selenium;
Creating the Constructor

If my exported JUnit 4 (Webdriver) groovy file's name is LoginTest.groovy I would create a constructor like the following.

public LoginTest( String url, int timeoutInSeconds) {
  baseUrl = url;
  timeout = timeoutInSeconds;
}

The constructor currently takes two parameters, a url and a timeout value in seconds. The url is set as the base url to test against.

Adding the Fields

You will need to add a timeout field and change a line of code in the test to use the timeout we set in the constructor.

Add a timeout field at top of the class under the baseUrl field or type int.

private String baseUrl;
private int timeout = 30;

Next you will want to set the timeout value for the webdriver using the timeout field you just created. Find the line of code that looks like this,

driver.manage().timeouts().implicitlyWait( 30, TimeUnit.SECONDS);

and change it to this,

driver.manage().timeouts().implicitlyWait( timeout, TimeUnit.SECONDS);

If you do not have that line of code just add it in the setUp() method.

PhantomJS

To get the script ready for PhantomJS modify your Groovy script like this:


Replace the following line
import org.openqa.selenium.firefox.FirefoxDriver;

with:

import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;

Replace the following line:

driver = new FirefoxDriver();

with:

DesiredCapabilities capabilities = DesiredCapabilities.phantomjs();
capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, "/usr/local/bin/phantomjs");
driver = new PhantomJSDriver(capabilities);

Now it should like this:

package selenium;

import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.Select;

public class LoginTest {
  private WebDriver driver;
  private String baseUrl;
  private int timeout = 30;
  private boolean acceptNextAlert = true;
  private StringBuffer verificationErrors = new StringBuffer();

  public LoginTest( String url, int timeoutInSeconds) {
    baseUrl = url;
    timeout = timeoutInSeconds;
  }

  @Before
  public void setUp() throws Exception {
    DesiredCapabilities capabilities = DesiredCapabilities.phantomjs();
    capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, "/usr/local/bin/phantomjs");
    driver = new PhantomJSDriver(capabilities);
    baseUrl = "https://zabbix.org/zabbix/";
    driver.manage().timeouts().implicitlyWait( timeout, TimeUnit.SECONDS);
  }

  @Test
  public void testLogin() throws Exception {
    driver.get(baseUrl + "/zabbix/");
    driver.findElement(By.linkText("sign in as guest")).click();
    driver.findElement(By.linkText("Problems")).click();
    driver.findElement(By.id("all_eventids")).click();
    driver.findElement(By.cssSelector("button[name=\"action\"]")).click();
    driver.findElement(By.id("message")).clear();
    driver.findElement(By.id("message")).sendKeys("OpenNMS Selenium Test :-)");
    driver.findElement(By.id("acknowledge_type_1")).click();
    driver.findElement(By.name("action")).click();
    driver.findElement(By.cssSelector("a.top-nav-signout")).click();
  }
...

Now copy your groovy file to $ONMS_HOME/etc/selenium/,

Prepare your OpenNMS System

  • Download PhantomJS and extract the archive
  • Place the binary phantomjs on your system in /usr/local/bin
  • Related to the PhantomJS docs it might be necessary to install fontconfig and/or libfontconfig.
apt install libfontconfig fontconfig
  • Download the Google JSON (GSON) library (an undocumented dependency) from the following web site and place the file in your OpenNMS library directory (ex. /usr/share/opennms/lib):
https://search.maven.org/remotecontent?filepath=com/google/code/gson/gson/2.3.1/gson-2.3.1.jar
apt install libhamcrest-java

Symlink the jars in /usr/share/java/hamcrest*.jar to /usr/share/opennms/lib/

[22:20]root@onms-server:/usr/share/opennms/lib# ll hamcrest-*
lrwxrwxrwx 1 root root 32 May  3 21:49 hamcrest-all.jar -> /usr/share/java/hamcrest-all.jar
lrwxrwxrwx 1 root root 33 May  3 21:49 hamcrest-core.jar -> /usr/share/java/hamcrest-core.jar
lrwxrwxrwx 1 root root 38 May  3 21:49 hamcrest-generator.jar -> /usr/share/java/hamcrest-generator.jar
lrwxrwxrwx 1 root root 36 May  3 21:49 hamcrest-library.jar -> /usr/share/java/hamcrest-library.jar
lrwxrwxrwx 1 root root 38 May  3 21:49 hamcrest-unit-test.jar -> /usr/share/java/hamcrest-unit-test.jar


  • OpenNMS needs to be restarted (but you can wait with it)

Poller Configuration

Note.png Documentation

Until now the SeleniumMonitor isn't documented. Please link to the docs if it's done: https://issues.opennms.org/browse/HZN-170

Configuration for the SeleniumMonitor is similar to the PageSequenceMonitor, there are two mandatory parameters you need to set, those parameters are base-url and selenium-sequence.


base-url

You have two options when it comes to setting the base-url, you can either set a static base-url or you can set it to use the monitored service's ip address to monitor.

Static url

<parameter key="base-url" value="http://google.com" />

Monitored Service IP address

<parameter key="base-url" value="http://${ipAddr}" />

Using https

<parameter key="base-url" value="https://${ipAddr}" />

Adding a port

<parameter key="base-url" value="http://${ipAddr}:8080" />
selenium-sequence

This property is the filename of the Groovy JUnit test sequence you want to run. The default directory for selenium sequences is $OPENNMS_HOME/etc/selenium .

<parameter key="selenium-test" value="LoginSequence.groovy" />


Note.png Hint

You can run multiple selenium unit tests within one Groovy JUnit test, giving you the flexibility to run multiple sequences at one time. The poll status will only result in available when every sequence has passed. If you put more than one sequence in the Groovy JUnit test all test will have to pass for availability to show as up.



Example Configuration

To configure the SeleniumMonitor add the following lines to your poller-configuration.xml

   <service name="Zabbix-Demo-Login" interval="300000" user-defined="false" status="on">
      <parameter key="retry" value="2" />
      <parameter key="timeout" value="3000" />
      <parameter key="rrd-repository" value="/usr/share/opennms/share/rrd/response" />
      <parameter key="rrd-base-name" value="LoginTest" /> <!-- change name accordingly -->
      <parameter key="ds-name" value="LoginTest" /> <!-- change name accordingly -->
      <parameter key="base-url" value="https://zabbix.org" /> <!-- using monitored service's ip address--> 
      <parameter key="selenium-test" value="LoginTest.groovy" />
    </service>

<monitor service="Zabbix-Demo-Login" class-name="org.opennms.netmgt.poller.monitors.SeleniumMonitor" />

After you have done your poller configurations, bind the defined service Zabbix-Demo-Login to a node of your choice and finally restart OpenNMS to load the configuration.

systemctl restart opennms

Note.png Response Time

Because we added the rrd-repository, rrd-base-name, ds-name parameters in the poller definition, we are able to check the sequence response time or how long it takes to successfully run the entire sequence