/* * 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.plugin.websphere.jmx; import com.ibm.websphere.management.AdminClient; import com.ibm.websphere.management.exception.ConnectorException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.hq.plugin.websphere.WebSphereProcess; import org.hyperic.hq.plugin.websphere.WebsphereDetector; import org.hyperic.hq.plugin.websphere.WebsphereProductPlugin; import org.hyperic.hq.plugin.websphere.WebsphereUtil; import org.hyperic.hq.product.MetricUnreachableException; import org.hyperic.hq.product.PluginException; import org.hyperic.hq.product.PluginUpdater; import org.hyperic.hq.product.ProductPlugin; import org.hyperic.hq.product.ServerResource; import org.hyperic.hq.product.ServiceResource; import org.hyperic.hq.product.jmx.ServiceTypeFactory; import org.hyperic.util.config.ConfigResponse; /** * WebSphere Application server and service discovery. */ public class WebsphereRuntimeDiscoverer { private Log log = LogFactory.getLog(WebsphereRuntimeDiscoverer.class.getName()); private ServiceTypeFactory serviceTypeFactory = new ServiceTypeFactory(); private String version; private WebsphereDetector serverDetector; static final WebSphereQuery[] serviceQueries = { new JDBCProviderQuery(), new ThreadPoolQuery(), new ApplicationQuery(),}; static final WebSphereQuery[] moduleQueries = { new EJBModuleQuery(), new WebModuleQuery(),}; private PluginUpdater pluginUpdater = new PluginUpdater(); public WebsphereRuntimeDiscoverer(String version, WebsphereDetector serverDetector) { this.version = version; this.serverDetector = serverDetector; } private List discover(AdminClient mServer, String domain, WebSphereQuery query) throws PluginException { List res = new ArrayList(); boolean isApp = query instanceof ApplicationQuery; ObjectName scope; try { scope = new ObjectName(domain + ":" + query.getScope() + ",*"); } catch (MalformedObjectNameException e) { throw new PluginException(e.getMessage(), e); } Set beans; try { query.setMBeanServer(mServer); beans = mServer.queryNames(scope, null); } catch (ConnectorException e) { throw new PluginException(e.getMessage(), e); } for (Iterator it = beans.iterator(); it.hasNext();) { ObjectName obj = (ObjectName) it.next(); WebSphereQuery type = query.cloneInstance(); type.setName(obj.getKeyProperty("name")); type.setObjectName(obj); type.getAttributes(mServer, obj); if (type.apply()) { res.add(type); if (isApp) { for (WebSphereQuery moduleQuery : moduleQueries) { moduleQuery.setParent(type); res.addAll(discover(mServer, domain, moduleQuery)); } } } else { log.debug("[discover] MBean discarted. obj:'" + obj + "'"); } } return res; } public List discoverServices(ConfigResponse config) throws PluginException { log.debug("[discoverServices] config=" + config); List res = new ArrayList(); try { AdminClient mServer = WebsphereUtil.getMBeanServer(config.toProperties()); String domain = mServer.getDomainName(); WebSphereProcess proc = new WebSphereProcess(config); NodeQuery nodeQuery = new NodeQuery(); nodeQuery.setName(proc.getNode()); nodeQuery.setCell(proc.getCell()); nodeQuery.setVersion(this.version); AppServerQuery serverQuery = new AppServerQuery(); serverQuery.setParent(nodeQuery); serverQuery.installpath = proc.getServerRoot(); List servers = discover(mServer, domain, serverQuery); for (int i = 0; i < servers.size(); i++) { WebSphereQuery server = (WebSphereQuery) servers.get(i); if (server.getName().equals(proc.getServer())) { res = discoverServices(mServer, server, proc); } } } catch (MetricUnreachableException e) { throw new PluginException(e.getMessage(), e); } catch (ConnectorException e) { if (log.isDebugEnabled()) { log.error(e.getMessage(), e); } } return res; } private List discoverServices(AdminClient mServer, WebSphereQuery server, WebSphereProcess proc) throws ConnectorException, PluginException { ConfigResponse productConfig; ConfigResponse metricConfig; ConfigResponse controlConfig = new ConfigResponse(); ConfigResponse cprops; String profile = proc.getServerRoot().substring(proc.getServerRoot().lastIndexOf("/") + 1); String domain = mServer.getDomainName(); List res = new ArrayList(); List services = new ArrayList(); for (int j = 0; j < serviceQueries.length; j++) { WebSphereQuery serviceQuery = serviceQueries[j]; serviceQuery.setParent(server); services.addAll(discover(mServer, domain, serviceQuery)); } for (int k = 0; k < services.size(); k++) { WebSphereQuery service = (WebSphereQuery) services.get(k); ServiceResource aiservice = new ServiceResource(); String svcType = service.getResourceName(); aiservice.setType(svcType); aiservice.setName(svcType + " " + profile + " " + proc.getCell() + " " + service.getFullName()); this.log.debug("discovered service: " + aiservice.getName()); this.log.debug(" + ObjectName: " + service.getObjectName()); this.log.debug(" + props: " + service.getProperties()); productConfig = new ConfigResponse(service.getProperties()); productConfig.setValue("server.name", proc.getServer()); metricConfig = new ConfigResponse(service.getMetricProperties()); aiservice.setProductConfig(productConfig); aiservice.setMeasurementConfig(metricConfig); if (service.hasControl()) { aiservice.setControlConfig(controlConfig); } cprops = new ConfigResponse(service.getCustomProperties()); aiservice.setCustomProperties(cprops); res.add(aiservice); } return res; } private boolean hasValidCredentials(AdminClient mServer, String domain, String node, String server) { String name = domain + ":" + "process=" + server + "," + "node=" + node + "," + "type=Perf,name=PerfMBean,*"; //try something that'll fail if global security is enabled. //don't want to report the servers/services until credentials //have been given to this admin instance. final String method = "getInstrumentationLevelString"; try { Object level = WebsphereUtil.invoke(mServer, name, method, new Object[0], new String[0]); log.debug(name + ": level=" + level); return true; } catch (Exception e) { this.log.error("Unable to determine PMI level for '" + name + "': " + e.getMessage()); return false; } } public List discoverServers(ConfigResponse config) throws PluginException { List aiservers = new ArrayList(); AdminClient mServer; String domain; WebSphereProcess parentProc = new WebSphereProcess(config); this.log.debug("discover using: " + config); try { mServer = WebsphereUtil.getMBeanServer(config.toProperties()); domain = mServer.getDomainName(); } catch (Exception e) { if (log.isDebugEnabled()) { log.error(e.getMessage(), e); } return aiservers; } String installpath = config.getValue(ProductPlugin.PROP_INSTALLPATH); String node = config.getValue(WebsphereProductPlugin.PROP_SERVER_NODE); NodeQuery nodeQuery = new NodeQuery(); nodeQuery.setName(node); nodeQuery.setVersion(this.version); AppServerQuery serverQuery = new AppServerQuery(); serverQuery.setParent(nodeQuery); serverQuery.installpath = installpath; List servers = discover(mServer, domain, serverQuery); if (servers.size() == 0) { //likely invalid node name log.warn("No servers discovered for node: " + node); } for (int i = 0; i < servers.size(); i++) { serverQuery = (AppServerQuery) servers.get(i); String srvName = serverQuery.getName(); ConfigResponse productConfig = new ConfigResponse(serverQuery.getProperties()); WebSphereProcess proc = new WebSphereProcess(config); proc.setServer(srvName); log.debug("[discoverServers] --> config=" + config); log.debug("[discoverServers] --> proc=" + proc); productConfig.merge(config, false); productConfig.setValue(WebsphereProductPlugin.PROP_SERVER_NAME, serverQuery.getName()); productConfig.setValue(WebsphereProductPlugin.PROP_ADMIN_HOST, serverDetector.getAdminHost(proc)); productConfig.setValue(WebsphereProductPlugin.PROP_ADMIN_PORT, serverDetector.getAdminPort(proc)); log.debug("[discoverServers] --> pc=" + productConfig); ServerResource server = new ServerResource(); aiservers.add(server); server.setInstallPath(installpath); server.setIdentifier(proc.getIdentifier()); String srvType = serverQuery.getResourceName(); if (serverQuery.getName().equals(parentProc.getServer())) { srvType = WebsphereProductPlugin.SERVER_NAME + " Admin " + serverQuery.getVersion(); } server.setType(srvType); server.setName(WebsphereDetector.getPlatformName() + " " + srvType + " " + proc.getServerName()); this.log.debug("discovered server: " + server.getName()); server.setProductConfig(productConfig); server.setMeasurementConfig(new ConfigResponse(serverQuery.getMetricProperties())); server.setControlConfig(serverDetector.getControlConfig(proc)); server.setCustomProperties(new ConfigResponse(serverQuery.getCustomProperties())); ArrayList services = new ArrayList(); if (!hasValidCredentials(mServer, domain, node, srvName)) { continue; } List res; try { res = discoverServices(mServer, serverQuery, proc); } catch (ConnectorException e) { throw new PluginException(e.getMessage(), e); } for (int n = 0; n < res.size(); n++) { server.addService((ServiceResource) res.get(n)); } } return aiservers; } }