/* * RHQ Management Platform * Copyright 2011, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.plugins.cassandra; import java.net.InetAddress; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.cassandra.net.MessagingService; import org.mc4j.ems.connection.bean.attribute.EmsAttribute; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.configuration.definition.PropertyDefinition; import org.rhq.core.domain.configuration.definition.PropertyDefinitionList; import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap; import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple; import org.rhq.core.domain.measurement.MeasurementDataNumeric; import org.rhq.core.domain.measurement.MeasurementReport; import org.rhq.core.domain.measurement.MeasurementScheduleRequest; import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport; import org.rhq.core.pluginapi.operation.OperationResult; import org.rhq.plugins.jmx.JMXComponent; import org.rhq.plugins.jmx.MBeanResourceComponent; /** * @author Stefan Negrea, Libor Zoubek * */ public class ComplexConfigurationResourceComponent extends MBeanResourceComponent<JMXComponent<?>> { /** * finds Cassandra node component * @return Cassandra component or null if it could not be found */ protected CassandraNodeComponent getCassandraComponent() { JMXComponent<?> component = this; while ((component != null) && !(component instanceof CassandraNodeComponent)) { if (component instanceof MBeanResourceComponent<?>) { component = ((MBeanResourceComponent<?>) component).getResourceContext().getParentResourceComponent(); } else { return null; } } return (CassandraNodeComponent) component; } /** * reads MBean attribute value (result type of Map<String,String> is expected) as operation result. Parameters 'keyName' and 'valueName' * denote names of SimpleProperties within produced OperationResult should by same as defined in plugin descriptor * @param name operation name = attributeName to read * @param keyName name of key to be written to result map * @param valueName name of value to be written to result map * @return Operation result with complex result (List of Map<name,value>) * @see MessagingService or StorageService plugin descriptor */ protected OperationResult invokeReadAttributeOperationComplexResult(String name, String keyName, String valueName) { OperationResult result = new OperationResult(); EmsAttribute attribute = getEmsBean().getAttribute(name); Object valueObject = attribute.refresh(); PropertyList resultList = new PropertyList("operationResult"); result.getComplexResults().put(resultList); if (valueObject instanceof Map<?, ?>) { @SuppressWarnings("unchecked") Map<String, String> map = (Map<String, String>) valueObject; for (Map.Entry<String, String> entry : map.entrySet()) { PropertyMap entryMap = new PropertyMap("entry"); resultList.add(entryMap); entryMap.put(new PropertySimple(keyName, entry.getKey())); entryMap.put(new PropertySimple(valueName, entry.getValue())); } } else { result.setErrorMessage("Failed to read response"); } return result; } @Override public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) { // handle special metrics starting with "host:" // such MBeans are expected to return Map<Host,Value> and we'll have to find value of current host (current node) Set<MeasurementScheduleRequest> filtered = new HashSet<MeasurementScheduleRequest>(requests.size()); for (MeasurementScheduleRequest request : requests) { if (!readHostMetric(request, report)) { filtered.add(request); } } super.getValues(report, filtered); } /** * reads host-related metric value. It is expected, that metric specified in `request` is prefixed * by "host:" in it's name and, returned MBean attribute value type is Map<Host,Value>. This method * finds current {@link CassandraNodeComponent#getHost()} in map and adds it's value into report * @param request * @param report * @return true if given request name was prefixed with "host:", false otherwise */ private boolean readHostMetric(MeasurementScheduleRequest request, MeasurementReport report) { if (!request.getName().startsWith("host:")) { return false; } CassandraNodeComponent cassandra = getCassandraComponent(); if (cassandra == null || cassandra.getHostAddress() == null) { return true; } InetAddress host = cassandra.getHostAddress(); String metricName = request.getName().substring(5); // strip out "host:" EmsAttribute attribute = getEmsBean().getAttribute(metricName); Object valueObject = attribute.refresh(); if (valueObject instanceof Map<?, ?>) { @SuppressWarnings("unchecked") Map<InetAddress, Float> hostMetric = (Map<InetAddress, Float>) valueObject; Float value = hostMetric.get(host); if (value == null) { // the inet address wasn't probably resolved, scan the map for (Map.Entry<InetAddress, Float> entry : hostMetric.entrySet()) { if (entry.getKey().getHostAddress().equals(host.getHostAddress())) { value = entry.getValue(); break; } } } if (value != null) { report.addData(new MeasurementDataNumeric(request, value.doubleValue())); } } return true; } @SuppressWarnings({ "unchecked", "deprecation" }) @Override public Configuration loadResourceConfiguration() { Configuration configuration = super.loadResourceConfiguration(); ConfigurationDefinition resourceConfigurationDefinition = this.resourceContext.getResourceType() .getResourceConfigurationDefinition(); for (PropertyDefinition propertyDefinition : resourceConfigurationDefinition.getPropertyDefinitions().values()) { if (propertyDefinition instanceof PropertyDefinitionList) { EmsAttribute attribute = getEmsBean().getAttribute(propertyDefinition.getName()); if (attribute != null) { Object result = attribute.refresh(); PropertyList propertyList = new PropertyList(propertyDefinition.getName()); if (result instanceof Map) { PropertyDefinitionMap propertyDefinitionMap = (PropertyDefinitionMap) ((PropertyDefinitionList) propertyDefinition) .getMemberDefinition(); String mapName = propertyDefinitionMap.getName(); Collection<PropertyDefinition> subPropertyDefinitions = propertyDefinitionMap .getOrderedPropertyDefinitions(); Iterator<PropertyDefinition> iterator = subPropertyDefinitions.iterator(); String keyName = ((PropertyDefinitionSimple) iterator.next()).getName(); String valueName = ((PropertyDefinitionSimple) iterator.next()).getName(); Map<Object, Object> mapValue = (Map<Object, Object>) result; PropertyMap propertyMap; for (Entry<Object, Object> entry : mapValue.entrySet()) { propertyMap = new PropertyMap(mapName); propertyMap.put(new PropertySimple(keyName, entry.getKey().toString())); propertyMap.put(new PropertySimple(valueName, entry.getValue().toString())); propertyList.add(propertyMap); } } else if (result instanceof Iterable<?>) { String entryName = ((PropertyDefinitionSimple) ((PropertyDefinitionList) propertyDefinition) .getMemberDefinition()).getName(); Iterable<?> iterable = (Iterable<?>) result; for (Object entry : iterable) { propertyList.add(new PropertySimple(entryName, entry.toString())); } } else if (result instanceof Object[]) { String entryName = ((PropertyDefinitionSimple) ((PropertyDefinitionList) propertyDefinition) .getMemberDefinition()).getName(); Object[] arrayValue = (Object[]) result; for (Object entry : arrayValue) { propertyList.add(new PropertySimple(entryName, entry.toString())); } } if (propertyList.getList().size() != 0) { configuration.put(propertyList); } } } } return configuration; } @Override public void updateResourceConfiguration(ConfigurationUpdateReport report) { // don't try to update the read only properties, it will fail super.updateResourceConfiguration(report, true); } }