/* * RHQ Management Platform * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.modules.plugins.wildfly10; import java.io.InputStream; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.measurement.MeasurementDataTrait; import org.rhq.core.domain.measurement.MeasurementReport; import org.rhq.core.domain.measurement.MeasurementScheduleRequest; import org.rhq.core.pluginapi.event.log.LogFileEventResourceComponentHelper; import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.operation.OperationResult; import org.rhq.core.pluginapi.support.SnapshotReportRequest; import org.rhq.core.pluginapi.support.SnapshotReportResults; import org.rhq.core.pluginapi.support.SupportFacet; import org.rhq.modules.plugins.wildfly10.helper.JdrReportRunner; import org.rhq.modules.plugins.wildfly10.json.Address; import org.rhq.modules.plugins.wildfly10.json.ComplexResult; import org.rhq.modules.plugins.wildfly10.json.ExpressionResolver; import org.rhq.modules.plugins.wildfly10.json.Operation; import org.rhq.modules.plugins.wildfly10.json.ReadAttribute; import org.rhq.modules.plugins.wildfly10.json.ReadResource; import org.rhq.modules.plugins.wildfly10.json.Result; /** * A component for a "Managed Server" Resource. * * @author Heiko W. Rupp */ @SuppressWarnings("unused") public class ManagedASComponent extends BaseComponent<HostControllerComponent<?>> implements SupportFacet { private static final String MANAGED_SERVER_TYPE_NAME = "Managed Server"; private LogFileEventResourceComponentHelper logFileEventDelegate; @Override public void start(ResourceContext<HostControllerComponent<?>> hostControllerComponentResourceContext) throws InvalidPluginConfigurationException, Exception { super.start(hostControllerComponentResourceContext); logFileEventDelegate = new LogFileEventResourceComponentHelper(context); logFileEventDelegate.startLogFileEventPollers(); } @Override public void stop() { super.stop(); logFileEventDelegate.stopLogFileEventPollers(); } /** * Get the availability of the managed AS server. We can't just check if * a connection succeeds, as the check runs against the API/HostController * and the managed server may still be down even if the connection succeeds. * @return Availability of the managed AS instance. */ @Override public AvailabilityType getAvailability() { if (context.getResourceType().getName().equals(MANAGED_SERVER_TYPE_NAME)) { Address theAddress = new Address(); String host = pluginConfiguration.getSimpleValue("domainHost", "local"); theAddress.add("host", host); theAddress.add("server-config", myServerName); Operation getStatus = new ReadAttribute(theAddress, "status"); Result result; try { result = getASConnection().execute(getStatus, AVAIL_OP_TIMEOUT_SECONDS); } catch (Exception e) { getLog().warn(e.getMessage()); return AvailabilityType.DOWN; } if (!result.isSuccess()) { if (result.isTimedout()) { return AvailabilityType.UNKNOWN; } return AvailabilityType.DOWN; } String msg = result.getResult().toString(); if (msg.contains("STARTED")) return AvailabilityType.UP; else return AvailabilityType.DOWN; } return super.getAvailability(); } public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) throws Exception { Set<MeasurementScheduleRequest> skmRequests = new HashSet<MeasurementScheduleRequest>(requests.size()); Set<MeasurementScheduleRequest> leftovers = new HashSet<MeasurementScheduleRequest>(requests.size()); for (MeasurementScheduleRequest request : requests) { if (request.getName().startsWith("_skm:")) { skmRequests.add(request); } else if (request.getName().equals("startTime")) { String path = getPath(); path = path.replace("server-config", "server"); Address address = new Address(path); address.add("core-service", "platform-mbean"); address.add("type", "runtime"); Operation op = new ReadAttribute(address, "start-time"); Result res = getASConnection().execute(op); if (res.isSuccess()) { Long startTime = (Long) res.getResult(); MeasurementDataTrait data = new MeasurementDataTrait(request, new Date(startTime).toString()); report.addData(data); } } else if (request.getName().equals("multicastAddress")) { collectMulticastAddressTrait(report, request); } else { leftovers.add(request); } } // Now handle the skm (this could go into a common method with BaseServerComponent's impl. if (skmRequests.size() > 0) { Address address = new Address(); ReadResource op = new ReadResource(address); op.includeRuntime(true); ComplexResult res = getASConnection().executeComplex(op); if (res.isSuccess()) { Map<String, Object> props = res.getResult(); for (MeasurementScheduleRequest request : skmRequests) { String requestName = request.getName(); String realName = requestName.substring(requestName.indexOf(':') + 1); String val = null; if (props.containsKey(realName)) { val = getStringValue(props.get(realName)); } if ("null".equals(val)) { if (realName.equals("product-name")) { val = "JBoss AS"; } else if (realName.equals("product-version")) { val = getStringValue(props.get("release-version")); } else if (getLog().isDebugEnabled()) { getLog().debug("Value for " + realName + " was 'null' and no replacement found"); } } MeasurementDataTrait data = new MeasurementDataTrait(request, val); report.addData(data); } } else if (getLog().isDebugEnabled()) { getLog().debug("getSKMRequests failed: " + res.getFailureDescription()); } } if (!leftovers.isEmpty()) super.getValues(report, leftovers); } @Override protected Address getServerAddress() { String serverConfigElement = getAddress().get(1); String serverName = serverConfigElement.substring(serverConfigElement.indexOf('=') + 1); Address serverAddress = getAddress().getParent(); serverAddress.add("server", serverName); return serverAddress; } @Override protected String getSocketBindingGroup() { String socketBindingGroup; try { socketBindingGroup = readAttribute("socket-binding-group"); } catch (Exception e) { socketBindingGroup = null; } if (socketBindingGroup == null) { String group; try { group = readAttribute("group"); } catch (Exception e) { group = null; } if (group != null) { Address groupAddress = new Address("server-group", group); try { socketBindingGroup = readAttribute(groupAddress, "socket-binding-group"); } catch (Exception e) { // ignore } } } return socketBindingGroup; } @Override public Configuration loadResourceConfiguration() throws Exception { Configuration configuration = super.loadResourceConfiguration(); // We need to deduct the domain host from the path, as it is not encoded in the resource itself. String serverPath = path; try { serverPath = serverPath.substring(0, serverPath.indexOf(",")); serverPath = serverPath.substring(serverPath.indexOf("=") + 1); } catch (RuntimeException e) { throw new Exception("Failed to extract hostname from server path [" + serverPath + "].", e); } configuration.put(new PropertySimple("hostname", serverPath)); ExpressionResolver resolver = getServerComponent().getExpressionResolver(); Operation op = new ReadResource(getAddress()); ComplexResult res = getASConnection().executeComplex(op); if (res.isSuccess()) { Map<String, Object> map = res.getResult(); String group = (String) map.get("group"); configuration.put(new PropertySimple("group", group)); Map<String, Object> sgMap = getServerGroupMap(group); String sbGroup = (String) map.get("socket-binding-group"); if (sbGroup == null) sbGroup = (String) sgMap.get("socket-binding-group"); configuration.put(new PropertySimple("socket-binding-group", sbGroup)); Boolean autoStart = resolver.getBoolean(map.get("auto-start")); configuration.put(new PropertySimple("auto-start", autoStart)); Integer offSet = resolver.getInteger(map.get("socket-binding-port-offset")); if (offSet == null) offSet = 0; configuration.put(new PropertySimple("socket-binding-port-offset", offSet)); } else { throw new RuntimeException("Could not load configuration from remote server"); } return configuration; } /** * Get the resource details of the server group with the given name * @param group Name of the server group to query * @return Map with the properties of the group. Or an empty map if the group does not exist. */ private Map<String, Object> getServerGroupMap(String group) { Operation op = new ReadResource("server-group", group); ComplexResult cr = getASConnection().executeComplex(op); if (cr.isSuccess()) { return cr.getResult(); } return Collections.emptyMap(); } @Override public OperationResult invokeOperation(String name, Configuration parameters) throws InterruptedException, Exception { Operation op = new Operation(name, getAddress()); op.addAdditionalProperty("blocking", Boolean.valueOf(parameters.getSimpleValue("blocking", "false"))); Result res = getASConnection().execute(op, Integer.parseInt(parameters.getSimpleValue("operationTimeout", "120"))); OperationResult opRes; if (res.isSuccess()) { opRes = new OperationResult("successfully invoked [" + name + "]"); } else { opRes = new OperationResult("Operation [" + name + "] failed"); opRes.setErrorMessage(res.getFailureDescription()); } return opRes; } @Override public SnapshotReportResults getSnapshotReport(SnapshotReportRequest request) throws Exception { if (AvailabilityType.UP.equals(getAvailability())) { if ("jdr".equals(request.getName())) { InputStream is = new JdrReportRunner(getServerAddress(), getASConnection()).getReport(); return new SnapshotReportResults(is); } return null; } throw new Exception("Cannot obtain report, resource is not UP"); } }