/* * RHQ Management Platform * Copyright (C) 2005-2012 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.coregui.client.admin.topology; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_ADDRESS; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_AFFINITY_GROUP; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_AGENT_TOKEN; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_LAST_AVAILABILITY_PING; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_LAST_AVAILABILITY_REPORT; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_NAME; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_PORT; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_REMOTE_ENDPOINT; import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_SERVER; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.types.Alignment; import com.smartgwt.client.types.Overflow; import com.smartgwt.client.types.VerticalAlignment; import com.smartgwt.client.types.VisibilityMode; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.Img; import com.smartgwt.client.widgets.Label; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.StaticTextItem; import com.smartgwt.client.widgets.layout.SectionStack; import com.smartgwt.client.widgets.layout.SectionStackSection; import org.rhq.core.domain.cloud.AffinityGroup; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.criteria.AgentCriteria; import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria; import org.rhq.core.domain.operation.OperationDefinition; import org.rhq.core.domain.operation.OperationRequestStatus; import org.rhq.core.domain.operation.ResourceOperationHistory; import org.rhq.core.domain.resource.Agent; import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.PageOrdering; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.LinkManager; import org.rhq.coregui.client.components.configuration.ConfigurationEditor; import org.rhq.coregui.client.components.table.TimestampCellFormatter; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.util.StringUtility; import org.rhq.coregui.client.util.enhanced.EnhancedVLayout; /** * Shows details of an agent. * * @author Jirka Kremser */ public class AgentDetailView extends EnhancedVLayout { private final int agentId; private static final int SECTION_COUNT = 3; private static final String LOADING_ICON = "ajax-loader.gif"; private final SectionStack sectionStack; private SectionStackSection detailsSection = null; private SectionStackSection failoverListSection = null; private SectionStackSection agentPluginsSection = null; private volatile boolean waitingForPlugins = false; private EnhancedVLayout pluginsSection; private Img loading; private volatile int initSectionCount = 0; public AgentDetailView(int agentId) { super(); this.agentId = agentId; setHeight100(); setWidth100(); setOverflow(Overflow.AUTO); sectionStack = new SectionStack(); sectionStack.setVisibilityMode(VisibilityMode.MULTIPLE); sectionStack.setWidth100(); sectionStack.setHeight100(); sectionStack.setMargin(5); sectionStack.setOverflow(Overflow.VISIBLE); } @Override protected void onInit() { super.onInit(); AgentCriteria criteria = new AgentCriteria(); criteria.addFilterId(agentId); GWTServiceLookup.getTopologyService().findAgentsByCriteria(criteria, new AsyncCallback<PageList<Agent>>() { public void onSuccess(final PageList<Agent> agents) { if (agents == null || agents.isEmpty() || agents.size() != 1) { CoreGUI.getErrorHandler().handleError( MSG.view_adminTopology_message_fetchAgentFail(String.valueOf(agentId))); initSectionCount = SECTION_COUNT; return; } prepareDetailsSection(agents.get(0)); prepareFailoverListSection(agents.get(0)); GWTServiceLookup.getTopologyService().getResourceIdOfAgent(agentId, new AsyncCallback<Integer>() { public void onSuccess(final Integer resourceId) { if (resourceId != null) { prepareAgentPluginsSection(sectionStack, resourceId); loadPlugins(resourceId); } else { initSectionCount = SECTION_COUNT; } } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError( MSG.view_adminTopology_message_fetchAgentFail(String.valueOf(agentId)) + " " + caught.getMessage(), caught); initSectionCount = SECTION_COUNT; } }); } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError( MSG.view_adminTopology_message_fetchAgentFail(String.valueOf(agentId)) + " " + caught.getMessage(), caught); initSectionCount = SECTION_COUNT; } }); } public boolean isInitialized() { return initSectionCount >= SECTION_COUNT; } @Override protected void onDraw() { super.onDraw(); // wait until we have all of the sections before we show them. We don't use InitializableView because, // it seems they are not supported (in the applicable renderView()) at this level. new Timer() { final long startTime = System.currentTimeMillis(); public void run() { if (isInitialized()) { if (null != detailsSection) { sectionStack.addSection(detailsSection); } if (null != failoverListSection) { sectionStack.addSection(failoverListSection); } if (null != agentPluginsSection) { sectionStack.addSection(agentPluginsSection); } addMember(sectionStack); markForRedraw(); } else { // don't wait forever, give up after 20s and show what we have long elapsedMillis = System.currentTimeMillis() - startTime; if (elapsedMillis > 20000) { initSectionCount = SECTION_COUNT; } schedule(100); // Reschedule the timer. } } }.run(); // fire the timer immediately } private void prepareFailoverListSection(Agent agent) { SectionStackSection section = new SectionStackSection(MSG.view_adminTopology_agentDetail_agentFailoverList()); section.setExpanded(true); ServerTableView agentsTable = new ServerTableView(agent.getId(), false); section.setItems(agentsTable); failoverListSection = section; ++initSectionCount; return; } private void prepareAgentPluginsSection(SectionStack stack, int resourceId) { SectionStackSection section = new SectionStackSection(MSG.view_adminConfig_agentPlugins()); section.setExpanded(false); loading = new Img(LOADING_ICON, 16, 16); loading.setValign(VerticalAlignment.CENTER); loading.setAlign(Alignment.CENTER); pluginsSection = new EnhancedVLayout(); pluginsSection.addMember(loading); section.setItems(pluginsSection); agentPluginsSection = section; ++initSectionCount; return; } protected Canvas buildResultsSection(ResourceOperationHistory operationHistory) { OperationRequestStatus status = operationHistory.getStatus(); if (status == OperationRequestStatus.SUCCESS || status == OperationRequestStatus.FAILURE) { EnhancedVLayout resultsSection = new EnhancedVLayout(); OperationDefinition operationDefinition = operationHistory.getOperationDefinition(); ConfigurationDefinition resultsConfigurationDefinition = operationDefinition .getResultsConfigurationDefinition(); if (resultsConfigurationDefinition != null && !resultsConfigurationDefinition.getPropertyDefinitions().isEmpty() && operationHistory.getResults() != null) { ConfigurationEditor editor = new ConfigurationEditor( operationDefinition.getResultsConfigurationDefinition(), operationHistory.getResults()); editor.setPreserveTextFormatting(true); editor.setReadOnly(true); resultsSection.addMember(editor); } else { Label noResultsLabel = new Label(MSG.view_operationHistoryDetails_noResults()); noResultsLabel.setHeight(17); resultsSection.addMember(noResultsLabel); } return resultsSection; } else { return null; } } private void prepareDetailsSection(Agent agent) { final DynamicForm form = new DynamicForm(); form.setMargin(10); form.setWidth100(); form.setWrapItemTitles(false); form.setNumCols(2); StaticTextItem nameItem = new StaticTextItem(FIELD_NAME.propertyName(), FIELD_NAME.title()); nameItem.setValue("<b>" + agent.getName() + "</b>"); StaticTextItem addressItem = new StaticTextItem(FIELD_ADDRESS.propertyName(), FIELD_ADDRESS.title()); addressItem.setValue(agent.getAddress()); StaticTextItem remoteEndpointItem = new StaticTextItem(FIELD_REMOTE_ENDPOINT.propertyName(), FIELD_REMOTE_ENDPOINT.title()); remoteEndpointItem.setValue(agent.getRemoteEndpoint()); StaticTextItem portItem = new StaticTextItem(FIELD_PORT.propertyName(), FIELD_PORT.title()); portItem.setValue(agent.getPort()); final StaticTextItem tokenItem = new StaticTextItem(FIELD_AGENT_TOKEN.propertyName(), FIELD_AGENT_TOKEN.title()); tokenItem.setValue(agent.getAgentToken()); StaticTextItem lastAvailabilityReportItem = new StaticTextItem(FIELD_LAST_AVAILABILITY_REPORT.propertyName(), FIELD_LAST_AVAILABILITY_REPORT.title()); String lastReport = agent.getLastAvailabilityReport() == null ? "unknown" : TimestampCellFormatter.format( Long.valueOf(agent.getLastAvailabilityReport()), TimestampCellFormatter.DATE_TIME_FORMAT_LONG); lastAvailabilityReportItem.setValue(lastReport); StaticTextItem lastAvailabilityPingItem = new StaticTextItem(FIELD_LAST_AVAILABILITY_PING.propertyName(), FIELD_LAST_AVAILABILITY_PING.title()); String lastPing = agent.getLastAvailabilityPing() == null ? "unknown" : TimestampCellFormatter.format( Long.valueOf(agent.getLastAvailabilityPing()), TimestampCellFormatter.DATE_TIME_FORMAT_LONG); lastAvailabilityPingItem.setValue(lastPing); // make clickable link for affinity group StaticTextItem affinityGroupItem = new StaticTextItem(FIELD_AFFINITY_GROUP.propertyName(), FIELD_AFFINITY_GROUP.title()); String affinityGroupItemText = ""; AffinityGroup ag = agent.getAffinityGroup(); if (ag != null && ag.getName() != null && !ag.getName().isEmpty()) { String detailsUrl = "#" + AffinityGroupTableView.VIEW_PATH + "/" + ag.getId(); String formattedValue = StringUtility.escapeHtml(ag.getName()); affinityGroupItemText = LinkManager.getHref(detailsUrl, formattedValue); } affinityGroupItem.setValue(affinityGroupItemText); StaticTextItem currentServerItem = new StaticTextItem(FIELD_SERVER.propertyName(), FIELD_SERVER.title()); String serverValue = null; if (agent.getServer() == null) { serverValue = ""; } else { String detailsUrl = "#" + ServerTableView.VIEW_PATH + "/" + agent.getServer().getId(); String formattedValue = StringUtility.escapeHtml(agent.getServer().getName()); serverValue = LinkManager.getHref(detailsUrl, formattedValue); } currentServerItem.setValue(serverValue); form.setItems(nameItem, addressItem, remoteEndpointItem, portItem, tokenItem, lastAvailabilityReportItem, lastAvailabilityPingItem, affinityGroupItem, currentServerItem); SectionStackSection section = new SectionStackSection(MSG.common_title_details()); section.setExpanded(true); section.setItems(form); detailsSection = section; ++initSectionCount; } private void loadPlugins(final int resourceId) { if (waitingForPlugins) { return; } waitingForPlugins = true; GWTServiceLookup.getOperationService().scheduleResourceOperation(resourceId, "retrieveAllPluginInfo", null, "Run by RHQ Server", 0, new AsyncCallback<Void>() { @Override public void onFailure(Throwable caught) { waitingForPlugins = false; } @Override public void onSuccess(Void result) { final ResourceOperationHistoryCriteria criteria = new ResourceOperationHistoryCriteria(); criteria.addFilterResourceIds(resourceId); criteria.addFilterOperationName("retrieveAllPluginInfo"); criteria.addSortEndTime(PageOrdering.DESC); criteria.fetchResults(true); new Timer() { @Override public void run() { GWTServiceLookup.getOperationService().findResourceOperationHistoriesByCriteria(criteria, new AsyncCallback<PageList<ResourceOperationHistory>>() { @Override public void onFailure(Throwable caught) { waitingForPlugins = false; } @Override public void onSuccess(PageList<ResourceOperationHistory> result) { if (!result.isEmpty()) { ResourceOperationHistory opHistory = result.get(0); if (opHistory.getStatus() == OperationRequestStatus.SUCCESS || opHistory.getStatus() == OperationRequestStatus.FAILURE) { pluginsSection.removeMembers(pluginsSection.getMembers()); pluginsSection.addMember(buildResultsSection(opHistory)); pluginsSection.markForRedraw(); waitingForPlugins = false; } else if (opHistory.getStatus() == OperationRequestStatus.INPROGRESS) { schedule(1000); } } } }); } }.schedule(700); } }); } }