/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.measurement.agent.client;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hyperic.hq.agent.AgentConnectionException;
import org.hyperic.hq.agent.AgentRemoteException;
import org.hyperic.hq.agent.client.AgentCommandsClient;
import org.hyperic.hq.agent.client.AgentCommandsClientFactory;
import org.hyperic.hq.appdef.shared.AgentManager;
import org.hyperic.hq.appdef.shared.AppdefEntityID;
import org.hyperic.hq.appdef.Agent;
import org.hyperic.hq.measurement.server.session.SRN;
import org.hyperic.hq.measurement.server.session.Measurement;
import org.hyperic.hq.measurement.agent.commands.GetMeasurements_args;
import org.hyperic.hq.measurement.agent.commands.GetMeasurements_result;
import org.hyperic.hq.measurement.agent.commands.ScheduleMeasurements_args;
import org.hyperic.hq.measurement.agent.commands.UnscheduleMeasurements_args;
import org.hyperic.hq.measurement.monitor.LiveMeasurementException;
import org.hyperic.hq.measurement.monitor.MonitorAgentException;
import org.hyperic.hq.product.MetricValue;
import org.hyperic.util.collection.ExpireMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* The AgentMonitor is a wrapper around the MeasurementClient, providing
* commonly used routines.
*/
@Component
public class AgentMonitorImpl implements AgentMonitor
{
private final Log log =
LogFactory.getLog(AgentMonitorImpl.class.getName());
private static final String ERR_REMOTE = "Error reported by Agent @ ";
private ExpireMap badAgents = new ExpireMap();
private static final long BAD_AGENT_EXPIRE = 60000;
private MeasurementCommandsClientFactory measurementCommandsClientFactory;
private AgentCommandsClientFactory agentCommandsClientFactory;
private AgentManager agentManager;
private SessionFactory sessionFactory;
@Autowired
public AgentMonitorImpl(MeasurementCommandsClientFactory measurementCommandsClientFactory,
AgentCommandsClientFactory agentCommandsClientFactory,
AgentManager agentManager,
SessionFactory sessionFactory
) {
this.measurementCommandsClientFactory = measurementCommandsClientFactory;
this.agentCommandsClientFactory = agentCommandsClientFactory;
this.agentManager = agentManager;
this.sessionFactory = sessionFactory;
}
/**
* Ping the agent to see if it is alive
* @param agent the agent connection info
* @return true if the agent is up, false otherwise
*/
public boolean ping(Agent agent) {
AgentCommandsClient client = agentCommandsClientFactory.getClient(agent);
try {
client.ping();
} catch (AgentRemoteException e) {
log.error("Agent exception: " + e.getMessage());
if (log.isDebugEnabled()) {
log.debug("Stacktrace: ", e);
}
return false;
} catch (AgentConnectionException e) {
log.error("Agent connection exception: " + e.getMessage());
if (log.isDebugEnabled()) {
log.debug("Stacktrace: ", e);
}
return false;
}
return true;
}
/**
* Schedule the measurement to be retrieved at specified intervals.
*
* @param srn The entity associated with the schedule
* @param schedule Information about the schedule of metrics to collect
*/
public void schedule(MeasurementCommandsClient client, SRN srn,
Measurement[] schedule)
throws AgentRemoteException, AgentConnectionException
{
ScheduleMeasurements_args args = new ScheduleMeasurements_args();
args.setSRN(srn);
for(int i=0; i<schedule.length; i++){
Measurement m = schedule[i];
String category = m.getTemplate().getCategory().getName();
args.addMeasurement(m.getDsn(), m.getInterval(),
m.getId().intValue(), m.getId().intValue(),
category);
}
client.scheduleMeasurements(args);
}
/**
* Unschedule measurements
*
* @param ids Array of entities to unschedule
*/
public void unschedule(Agent agent, AppdefEntityID[] ids)
throws MonitorAgentException
{
// If the agent's bad in the last 60 seconds, let's not worry about it
if (badAgents.containsKey(agent.getAddress()))
return;
try {
MeasurementCommandsClient client =
measurementCommandsClientFactory.getClient(agent);
UnscheduleMeasurements_args args =
new UnscheduleMeasurements_args();
for (int i = 0; i < ids.length; i++) {
args.addEntity(ids[i]);
}
client.unscheduleMeasurements(args);
} catch (AgentConnectionException e) {
this.log.warn(ERR_REMOTE + agent.connectionString() +
": " + e.getMessage());
// Track bad agent
badAgents.put(agent.getAddress(), agent, BAD_AGENT_EXPIRE);
throw new MonitorAgentException(e.getMessage(), e);
} catch (AgentRemoteException e) {
String emsg = ERR_REMOTE + agent.connectionString() +
": " + e.getMessage();
this.log.warn(emsg);
// Track bad agent
badAgents.put(agent.getAddress(), agent, BAD_AGENT_EXPIRE);
throw new MonitorAgentException(emsg, e);
}
}
/** Get the live value
* @param agentID the ID of the agent to talk to
* @param dsns the DSNs that identifies the values to fetch
*/
@Transactional(readOnly = true)
public MetricValue[] getLiveValues(int agentId, String[] dsns)
throws MonitorAgentException, LiveMeasurementException
{
Agent agent = agentManager.getAgent(agentId);
Session hSession = sessionFactory.getCurrentSession();
hSession.update(agent);
return getLiveValues(agent, dsns);
}
/** Get the live value
* @param agent the agent to talk to
* @param dsns the DSNs that identifies the values to fetch
*/
public MetricValue[] getLiveValues(Agent agent, String[] dsns)
throws MonitorAgentException, LiveMeasurementException
{
try {
if (log.isDebugEnabled()) {
log.debug("Getting live values for agent: " + agent + ", dsns: " + dsns);
}
GetMeasurements_result result;
GetMeasurements_args args;
MetricValue[] res;
args = new GetMeasurements_args();
for(int i=0; i<dsns.length; i++){
args.addMeasurement(dsns[i]);
}
MeasurementCommandsClient client =
measurementCommandsClientFactory.getClient(agent);
result = client.getMeasurements(args);
if (log.isDebugEnabled()) {
log.debug("Got live values result for agent: " + agent);
}
res = new MetricValue[dsns.length];
for(int i=0; i<dsns.length; i++){
res[i] = result.getMeasurement(i);
if(res[i] == null){
throw new LiveMeasurementException(result.getException(i));
}
}
return res;
} catch (AgentConnectionException e) {
final String emsg = ERR_REMOTE + agent.connectionString() +
": " + e.getMessage();
this.log.warn(emsg);
throw new MonitorAgentException(e.getMessage(), e);
} catch (AgentRemoteException e) {
final String emsg = ERR_REMOTE + agent.connectionString() +
": " + e.getMessage();
this.log.warn(emsg);
throw new MonitorAgentException(emsg, e);
}
}
}