Forum Discussion

Hshukla's avatar
Hshukla
Icon for Neophyte rankNeophyte
2 months ago

Datapoints configuration Discussion

Hello Team, I am trying to create a custom datasource to check the service status. It retrieves a list of services from the host properties(auto.service.names), connects to the host using SSH, checks the status of each service using the systemctl command, and outputs the results.

Active Discovery Script: 

import com.santaba.agent.groovyapi.expect.Expect;
import com.santaba.agent.groovyapi.snmp.Snmp;
import com.santaba.agent.groovyapi.http.*;
import com.santaba.agent.groovyapi.jmx.*;
import org.xbill.DNS.*;

// Get the service names from the host property
def serviceNames = hostProps.get("auto.service.names") ?: ""
def serviceArray = serviceNames.split(",").collect { it.trim() }

// SSH details for connecting to the host
host = hostProps.get("system.hostname")
user = hostProps.get("ssh.user")
pass = hostProps.get("ssh.pass")
port = hostProps.get("ssh.port")?.toInteger() ?: 22
cert = hostProps.get("ssh.cert") ?: '~/.ssh/id_rsa'
timeout = 15000 // Timeout in milliseconds

// Initialize JSCH for SSH connection
import com.jcraft.jsch.JSch

def getServiceStatus(serviceName) {
    def command = "systemctl is-active ${serviceName}"
    return getCommandOutput(command).trim()
}

def getCommandOutput(String input_command) {
    def output = ""
    def session = null
    def channel = null

    try {
        def jsch = new JSch()
        if (user && !pass) {
            jsch.addIdentity(cert)
        }

        session = jsch.getSession(user, host, port)
        session.setConfig("StrictHostKeyChecking", "no")
        session.setTimeout(timeout)

        if (pass) {
            session.setPassword(pass)
        }

        session.connect()

        channel = session.openChannel("exec")
        channel.setCommand(input_command)
        def commandOutput = channel.getInputStream()
        channel.connect()
        output = commandOutput.text

    } finally {
        if (channel) {
            channel.disconnect()
        }
        if (session) {
            session.disconnect()
        }
    }

    return output
}

// Output each service with its status
serviceArray.each { serviceName ->
    def status = getServiceStatus(serviceName)
    println "${serviceName}##${serviceName}##Status: ${status}"
}

return 0

Collection Script:

Below, I am trying to use the ##WILDVALUE## from the active discovery script to collect the service status value. 

com.jcraft.jsch.JSch // Initialize JSCH for SSH connection

// SSH details for connecting to the host
host = hostProps.get("system.hostname")
user = hostProps.get("ssh.user")
pass = hostProps.get("ssh.pass")
port = hostProps.get("ssh.port")?.toInteger() ?: 22
cert = hostProps.get("ssh.cert") ?: '~/.ssh/id_rsa'
timeout = 15000 // Timeout in milliseconds

// Function to retrieve the service status
def getServiceStatus(serviceName) {
    def command = "systemctl is-active ${serviceName}"
    def result = getCommandOutput(command)
    return result?.trim()
}

// Function to execute command and retrieve output
def getCommandOutput(String command) {
    def output = ""
    def session = null
    def channel = null
    def reader = null

    try {
        def jsch = new JSch()
        if (user && !pass) {
            jsch.addIdentity(cert)
        }

        session = jsch.getSession(user, host, port)
        session.setConfig("StrictHostKeyChecking", "no")
        session.setTimeout(timeout)

        if (pass) {
            session.setPassword(pass)
        }

        session.connect()

        channel = session.openChannel("exec")
        channel.setCommand(command)
        channel.setInputStream(null)
        channel.setErrStream(System.err)

        reader = new BufferedReader(new InputStreamReader(channel.getInputStream()))
        channel.connect()

        def line
        while ((line = reader.readLine()) != null) {
            output += line + "\n"
        }

        // Ensuring the channel finishes before disconnecting
        while (!channel.isClosed()) {
            Thread.sleep(100)
        }

    } catch (Exception e) {
        println "Error executing command: ${e.message}"
    } finally {
        reader?.close()
        channel?.disconnect()
        session?.disconnect()
    }

    return output
}

// Retrieve the current service name based on ##WILDVALUE##
def serviceName = datasourceinstanceProps.values().collect { it.wildvalue }.find { it != null }
if (serviceName) {
    
    def status = getServiceStatus(serviceName)
    def statusValue = (status == "active") ? 1 : 0
    println "Service:${serviceName} Status:${statusValue}"
    return statusValue
} else {
    println "Error: No service name found for ##WILDVALUE##."
    return null
}

I need help creating the datapoint to collect service status value. Thanks in advance. 

The error I am currently getting: 

param prefix is not invalid in format - (valid_prefixes=[datacollector.], method=namevalue, param=datacollector)

 

  • Is this a "SCRIPT" or "BATCHSCRIPT" type of DataSource? What is the Datapoint's "Interpret output with" set to?

    There is likely a specific format you need to output your Collection Script. I didn't look at your code too closely but if your using BatchScript you likely want to use something like this for the output:

    println "${serviceName}.Status=${statusValue}"

     

  • Have you tried a WMI method? If SSH is the method you need to use that's fine but let me know if you're open to other methods. 
    We also have a PowerShell script for detecting service status and attempting to restart the service before alerting.