[rhq] modules/enterprise
by Jay Shaughnessy
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java | 40 ++-
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/HistoryGroupResourceConfigurationMembers.java | 102 ++++++++--
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/HistoryGroupPluginConfigurationMembers.java | 102 ++++++++--
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java | 3
4 files changed, 205 insertions(+), 42 deletions(-)
New commits:
commit 01126cb3b531ac706e8280ab97f049d44db91399
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Tue Mar 15 11:01:27 2011 -0400
Ancestry (Disambiguation) Work
- Add Ancestry to Group Resource Config Member view
- Add Ancestry to Group Plugin Config Member view
- Fix issue with Operation subsystem view
- Fix small optimization issue in ConfigurationHistoryDataSource
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java
index 50593ec..6553b56 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java
@@ -43,12 +43,13 @@ import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import org.rhq.core.domain.operation.OperationRequestStatus;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
+import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.components.table.TableAction;
import org.rhq.enterprise.gui.coregui.client.components.table.TableSection;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
-import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.operation.history.ResourceOperationHistoryDataSource;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableHTMLPane;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableWindow;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
/**
* @author Greg Hinkle
@@ -238,19 +239,23 @@ public abstract class AbstractOperationHistoryListView<T extends AbstractOperati
}
protected ListGridField createResourceField() {
- ListGridField resourceField = new ListGridField(ResourceOperationHistoryDataSource.Field.RESOURCE, MSG
- .common_title_resource());
+ ListGridField resourceField = new ListGridField(AncestryUtil.RESOURCE_NAME, MSG.common_title_resource());
resourceField.setAlign(Alignment.LEFT);
resourceField.setCellAlign(Alignment.LEFT);
- //resourceField.setSuppressValueIcon(true);
- //resourceField.setValueIcons(new HashMap<String, String>(0));
- /*resourceField.setCellFormatter(new CellFormatter() {
- public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
- Resource resource = (Resource) value;
- String url = LinkManager.getResourceLink(resource.getId());
- return "<a href=\"" + url + "\">" + resource.getName() + "</a>";
+ resourceField.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
+ String url = LinkManager.getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+ return SeleniumUtility.getLocatableHref(url, o.toString(), null);
}
- });*/
+ });
+ resourceField.setShowHover(true);
+ resourceField.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+ }
+ });
+
return resourceField;
}
@@ -258,6 +263,19 @@ public abstract class AbstractOperationHistoryListView<T extends AbstractOperati
ListGridField ancestryField = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, MSG.common_title_ancestry());
ancestryField.setAlign(Alignment.LEFT);
ancestryField.setCellAlign(Alignment.LEFT);
+ ancestryField.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return listGridRecord.getAttributeAsString(AncestryUtil.RESOURCE_ANCESTRY_VALUE);
+ }
+ });
+ ancestryField.setShowHover(true);
+ ancestryField.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getAncestryHoverHTML(listGridRecord, 0);
+ }
+ });
+
return ancestryField;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/HistoryGroupResourceConfigurationMembers.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/HistoryGroupResourceConfigurationMembers.java
index 99fd567..8ea5782 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/HistoryGroupResourceConfigurationMembers.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/configuration/HistoryGroupResourceConfigurationMembers.java
@@ -20,12 +20,15 @@ package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.configurat
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HoverCustomizer;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
@@ -37,6 +40,8 @@ import org.rhq.core.domain.configuration.AbstractConfigurationUpdate;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.composite.ResourcePermission;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
@@ -49,8 +54,12 @@ import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.gwt.ConfigurationGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
/**
* Shows a table of individual resource members that belonged to the group when the group configuration was updated.
@@ -93,7 +102,36 @@ public class HistoryGroupResourceConfigurationMembers extends LocatableVLayout {
@Override
protected void configureTable() {
- ListGridField fieldResource = new ListGridField(DataSource.Field.RESOURCELINK, MSG.common_title_resource());
+ ListGridField fieldResource = new ListGridField(AncestryUtil.RESOURCE_NAME, MSG.common_title_resource());
+ fieldResource.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
+ String url = LinkManager
+ .getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+ return SeleniumUtility.getLocatableHref(url, o.toString(), null);
+ }
+ });
+ fieldResource.setShowHover(true);
+ fieldResource.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+ }
+ });
+
+ ListGridField fieldAncestry = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, MSG.common_title_ancestry());
+ fieldAncestry.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return listGridRecord.getAttributeAsString(AncestryUtil.RESOURCE_ANCESTRY_VALUE);
+ }
+ });
+ fieldAncestry.setShowHover(true);
+ fieldAncestry.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getAncestryHoverHTML(listGridRecord, 0);
+ }
+ });
+
ListGridField fieldDateCreated = new ListGridField(DataSource.Field.DATECREATED, MSG
.common_title_dateCreated());
ListGridField fieldLastUpdated = new ListGridField(DataSource.Field.LASTUPDATED, MSG
@@ -101,9 +139,10 @@ public class HistoryGroupResourceConfigurationMembers extends LocatableVLayout {
ListGridField fieldStatus = new ListGridField(DataSource.Field.STATUS, MSG.common_title_status());
ListGridField fieldUser = new ListGridField(DataSource.Field.USER, MSG.common_title_user());
- fieldResource.setWidth("*");
- fieldDateCreated.setWidth("15%");
- fieldLastUpdated.setWidth("15%");
+ fieldResource.setWidth("30%");
+ fieldAncestry.setWidth("*");
+ fieldDateCreated.setWidth(150);
+ fieldLastUpdated.setWidth(150);
fieldStatus.setWidth("10%");
fieldUser.setWidth("10%");
@@ -143,8 +182,8 @@ public class HistoryGroupResourceConfigurationMembers extends LocatableVLayout {
});
ListGrid listGrid = getListGrid();
- listGrid.setFields(fieldResource, fieldDateCreated, fieldLastUpdated, fieldStatus, fieldUser);
- listGrid.setLinkTextProperty(DataSource.Field.RESOURCENAME);
+ listGrid
+ .setFields(fieldResource, fieldAncestry, fieldDateCreated, fieldLastUpdated, fieldStatus, fieldUser);
}
private String getStatusHtmlString(Record record) {
@@ -179,8 +218,6 @@ public class HistoryGroupResourceConfigurationMembers extends LocatableVLayout {
public class Field {
public static final String ID = "id";
- public static final String RESOURCELINK = "resourceLink";
- public static final String RESOURCENAME = "resourceName";
public static final String DATECREATED = "dateCreated";
public static final String LASTUPDATED = "lastUpdated";
public static final String STATUS = "status";
@@ -198,13 +235,18 @@ public class HistoryGroupResourceConfigurationMembers extends LocatableVLayout {
ListGridRecord record = new ListGridRecord();
record.setAttribute(Field.ID, from.getId());
- record.setAttribute(Field.RESOURCELINK, LinkManager.getResourceLink(from.getResource().getId()));
- record.setAttribute(Field.RESOURCENAME, from.getResource().getName());
record.setAttribute(Field.DATECREATED, new Date(from.getCreatedTime()));
record.setAttribute(Field.LASTUPDATED, new Date(from.getModifiedTime()));
record.setAttribute(Field.USER, from.getSubjectName());
record.setAttribute(Field.STATUS, from.getStatus().name());
+ // for ancestry handling
+ Resource resource = from.getResource();
+ record.setAttribute(AncestryUtil.RESOURCE_ID, resource.getId());
+ record.setAttribute(AncestryUtil.RESOURCE_NAME, resource.getName());
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY, resource.getAncestry());
+ record.setAttribute(AncestryUtil.RESOURCE_TYPE_ID, resource.getResourceType().getId());
+
record.setAttribute(Field.OBJECT, from);
return record;
@@ -217,17 +259,47 @@ public class HistoryGroupResourceConfigurationMembers extends LocatableVLayout {
ResourceConfigurationUpdateCriteria criteria = new ResourceConfigurationUpdateCriteria();
criteria
.addFilterGroupConfigurationUpdateId(HistoryGroupResourceConfigurationMembers.this.groupUpdateId);
- // TODO need to disambiguate resources
criteria.fetchResource(true);
configurationService.findResourceConfigurationUpdatesByCriteria(criteria,
new AsyncCallback<PageList<ResourceConfigurationUpdate>>() {
@Override
- public void onSuccess(PageList<ResourceConfigurationUpdate> result) {
- response.setData(buildRecords(result));
- response.setTotalRows(result.getTotalSize());
- processResponse(request.getRequestId(), response);
+ public void onSuccess(final PageList<ResourceConfigurationUpdate> result) {
+ HashSet<Integer> typesSet = new HashSet<Integer>();
+ HashSet<String> ancestries = new HashSet<String>();
+ for (ResourceConfigurationUpdate update : result) {
+ Resource resource = update.getResource();
+ typesSet.add(resource.getResourceType().getId());
+ ancestries.add(resource.getAncestry());
+ }
+
+ // In addition to the types of the result resources, get the types of their ancestry
+ typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
+
+ ResourceTypeRepository typeRepo = ResourceTypeRepository.Cache.getInstance();
+ typeRepo.getResourceTypes(typesSet.toArray(new Integer[typesSet.size()]),
+ new TypesLoadedCallback() {
+ @Override
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ // Smartgwt has issues storing a Map as a ListGridRecord attribute. Wrap it in a pojo.
+ AncestryUtil.MapWrapper typesWrapper = new AncestryUtil.MapWrapper(types);
+
+ Record[] records = buildRecords(result);
+ for (Record record : records) {
+ // To avoid a lot of unnecessary String construction, be lazy about building ancestry hover text.
+ // Store the types map off the records so we can build a detailed hover string as needed.
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_TYPES, typesWrapper);
+
+ // Build the decoded ancestry Strings now for display
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_VALUE, AncestryUtil
+ .getAncestryValue(record));
+ }
+ response.setData(records);
+ response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ processResponse(request.getRequestId(), response);
+ }
+ });
}
@Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/HistoryGroupPluginConfigurationMembers.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/HistoryGroupPluginConfigurationMembers.java
index 2af2fcf..ae76963 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/HistoryGroupPluginConfigurationMembers.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/HistoryGroupPluginConfigurationMembers.java
@@ -20,12 +20,15 @@ package org.rhq.enterprise.gui.coregui.client.inventory.groups.detail.inventory;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.ListGridFieldType;
+import com.smartgwt.client.widgets.grid.CellFormatter;
import com.smartgwt.client.widgets.grid.HoverCustomizer;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
@@ -37,6 +40,8 @@ import org.rhq.core.domain.configuration.AbstractConfigurationUpdate;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.criteria.PluginConfigurationUpdateCriteria;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.composite.ResourcePermission;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
@@ -49,8 +54,12 @@ import org.rhq.enterprise.gui.coregui.client.components.buttons.BackButton;
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.gwt.ConfigurationGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
/**
* Shows a table of individual resource members that belonged to the group when the group configuration was updated.
@@ -92,7 +101,36 @@ public class HistoryGroupPluginConfigurationMembers extends LocatableVLayout {
@Override
protected void configureTable() {
- ListGridField fieldResource = new ListGridField(DataSource.Field.RESOURCELINK, MSG.common_title_resource());
+ ListGridField fieldResource = new ListGridField(AncestryUtil.RESOURCE_NAME, MSG.common_title_resource());
+ fieldResource.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
+ String url = LinkManager
+ .getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+ return SeleniumUtility.getLocatableHref(url, o.toString(), null);
+ }
+ });
+ fieldResource.setShowHover(true);
+ fieldResource.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+ }
+ });
+
+ ListGridField fieldAncestry = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, MSG.common_title_ancestry());
+ fieldAncestry.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return listGridRecord.getAttributeAsString(AncestryUtil.RESOURCE_ANCESTRY_VALUE);
+ }
+ });
+ fieldAncestry.setShowHover(true);
+ fieldAncestry.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getAncestryHoverHTML(listGridRecord, 0);
+ }
+ });
+
ListGridField fieldDateCreated = new ListGridField(DataSource.Field.DATECREATED, MSG
.common_title_dateCreated());
ListGridField fieldLastUpdated = new ListGridField(DataSource.Field.LASTUPDATED, MSG
@@ -100,9 +138,10 @@ public class HistoryGroupPluginConfigurationMembers extends LocatableVLayout {
ListGridField fieldStatus = new ListGridField(DataSource.Field.STATUS, MSG.common_title_status());
ListGridField fieldUser = new ListGridField(DataSource.Field.USER, MSG.common_title_user());
- fieldResource.setWidth("*");
- fieldDateCreated.setWidth("15%");
- fieldLastUpdated.setWidth("15%");
+ fieldResource.setWidth("30%");
+ fieldAncestry.setWidth("*");
+ fieldDateCreated.setWidth(150);
+ fieldLastUpdated.setWidth(150);
fieldStatus.setWidth("10%");
fieldUser.setWidth("10%");
@@ -142,8 +181,8 @@ public class HistoryGroupPluginConfigurationMembers extends LocatableVLayout {
});
ListGrid listGrid = getListGrid();
- listGrid.setFields(fieldResource, fieldDateCreated, fieldLastUpdated, fieldStatus, fieldUser);
- listGrid.setLinkTextProperty(DataSource.Field.RESOURCENAME);
+ listGrid
+ .setFields(fieldResource, fieldAncestry, fieldDateCreated, fieldLastUpdated, fieldStatus, fieldUser);
}
private String getStatusHtmlString(Record record) {
@@ -178,8 +217,6 @@ public class HistoryGroupPluginConfigurationMembers extends LocatableVLayout {
public class Field {
public static final String ID = "id";
- public static final String RESOURCELINK = "resourceLink";
- public static final String RESOURCENAME = "resourceName";
public static final String DATECREATED = "dateCreated";
public static final String LASTUPDATED = "lastUpdated";
public static final String STATUS = "status";
@@ -197,13 +234,18 @@ public class HistoryGroupPluginConfigurationMembers extends LocatableVLayout {
ListGridRecord record = new ListGridRecord();
record.setAttribute(Field.ID, from.getId());
- record.setAttribute(Field.RESOURCELINK, LinkManager.getResourceLink(from.getResource().getId()));
- record.setAttribute(Field.RESOURCENAME, from.getResource().getName());
record.setAttribute(Field.DATECREATED, new Date(from.getCreatedTime()));
record.setAttribute(Field.LASTUPDATED, new Date(from.getModifiedTime()));
record.setAttribute(Field.USER, from.getSubjectName());
record.setAttribute(Field.STATUS, from.getStatus().name());
+ // for ancestry handling
+ Resource resource = from.getResource();
+ record.setAttribute(AncestryUtil.RESOURCE_ID, resource.getId());
+ record.setAttribute(AncestryUtil.RESOURCE_NAME, resource.getName());
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY, resource.getAncestry());
+ record.setAttribute(AncestryUtil.RESOURCE_TYPE_ID, resource.getResourceType().getId());
+
record.setAttribute(Field.OBJECT, from);
return record;
@@ -215,17 +257,47 @@ public class HistoryGroupPluginConfigurationMembers extends LocatableVLayout {
PluginConfigurationUpdateCriteria criteria = new PluginConfigurationUpdateCriteria();
criteria.addFilterGroupConfigurationUpdateId(HistoryGroupPluginConfigurationMembers.this.groupUpdateId);
- // TODO need to disambiguate resources
criteria.fetchResource(true);
configurationService.findPluginConfigurationUpdatesByCriteria(criteria,
new AsyncCallback<PageList<PluginConfigurationUpdate>>() {
@Override
- public void onSuccess(PageList<PluginConfigurationUpdate> result) {
- response.setData(buildRecords(result));
- response.setTotalRows(result.getTotalSize());
- processResponse(request.getRequestId(), response);
+ public void onSuccess(final PageList<PluginConfigurationUpdate> result) {
+ HashSet<Integer> typesSet = new HashSet<Integer>();
+ HashSet<String> ancestries = new HashSet<String>();
+ for (PluginConfigurationUpdate update : result) {
+ Resource resource = update.getResource();
+ typesSet.add(resource.getResourceType().getId());
+ ancestries.add(resource.getAncestry());
+ }
+
+ // In addition to the types of the result resources, get the types of their ancestry
+ typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
+
+ ResourceTypeRepository typeRepo = ResourceTypeRepository.Cache.getInstance();
+ typeRepo.getResourceTypes(typesSet.toArray(new Integer[typesSet.size()]),
+ new TypesLoadedCallback() {
+ @Override
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ // Smartgwt has issues storing a Map as a ListGridRecord attribute. Wrap it in a pojo.
+ AncestryUtil.MapWrapper typesWrapper = new AncestryUtil.MapWrapper(types);
+
+ Record[] records = buildRecords(result);
+ for (Record record : records) {
+ // To avoid a lot of unnecessary String construction, be lazy about building ancestry hover text.
+ // Store the types map off the records so we can build a detailed hover string as needed.
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_TYPES, typesWrapper);
+
+ // Build the decoded ancestry Strings now for display
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_VALUE, AncestryUtil
+ .getAncestryValue(record));
+ }
+ response.setData(records);
+ response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ processResponse(request.getRequestId(), response);
+ }
+ });
}
@Override
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java
index 2b0709e..3a28dcc 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java
@@ -89,7 +89,6 @@ public class ConfigurationHistoryDataSource extends AbstractConfigurationHistory
}
public void onSuccess(final PageList<ResourceConfigurationUpdate> result) {
- final ListGridRecord[] records = buildRecords(result);
if (resourceId == null) {
HashSet<Integer> typesSet = new HashSet<Integer>();
HashSet<String> ancestries = new HashSet<String>();
@@ -129,6 +128,8 @@ public class ConfigurationHistoryDataSource extends AbstractConfigurationHistory
return;
}
+ final ListGridRecord[] records = buildRecords(result);
+
// we are obtaining a single resource's history items. Let's find out which is
// its latest, current config item so we can mark it as such
getConfigurationService().getLatestResourceConfigurationUpdate(resourceId.intValue(),
13 years, 3 months
[rhq] modules/enterprise
by Jay Shaughnessy
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/AbstractConfigurationHistoryDataSource.java | 58 +++++++---
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java | 49 +++++++-
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationHistoryDataSource.java | 49 +++++++-
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ConfigurationGWTServiceImpl.java | 38 ++++++
4 files changed, 167 insertions(+), 27 deletions(-)
New commits:
commit 1d07b7f622c024bde84191b1ac573b27e63b205f
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Mar 14 20:39:53 2011 -0400
Ancestry (Disambiguation) for Resource and Plugin config history
- added resource filtering for the Update entities.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/AbstractConfigurationHistoryDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/AbstractConfigurationHistoryDataSource.java
index a50e8a8..4420169 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/AbstractConfigurationHistoryDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/AbstractConfigurationHistoryDataSource.java
@@ -44,6 +44,7 @@ import org.rhq.enterprise.gui.coregui.client.ErrorMessageWindow;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
import org.rhq.enterprise.gui.coregui.client.gwt.ConfigurationGWTServiceAsync;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource;
import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
@@ -59,11 +60,9 @@ public abstract class AbstractConfigurationHistoryDataSource<T extends AbstractR
public static abstract class Field {
public static final String ID = "id";
- public static final String RESOURCE = "resource";
public static final String CREATED_TIME = "createdTime";
public static final String STATUS = "status";
public static final String SUBJECT = "subject";
- public static final String RESOURCE_TYPE_ID = "resourceTypeId";
public static final String CONFIGURATION = "configuration";
public static final String GROUP_CONFIG_UPDATE_ID = "groupConfigUpdateId";
public static final String GROUP_ID = "groupId"; // will only be non-null if group config update id is non-null
@@ -212,27 +211,46 @@ public abstract class AbstractConfigurationHistoryDataSource<T extends AbstractR
// determine the widths of our columns
if (includeResourceFields) {
- ListGridField resourceField = new ListGridField(Field.RESOURCE, MSG.common_title_resource());
- resourceField.setCellFormatter(new CellFormatter() {
+ ListGridField resourceNameField = new ListGridField(AncestryUtil.RESOURCE_NAME, MSG.common_title_resource());
+ resourceNameField.setCellFormatter(new CellFormatter() {
public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
- if (listGridRecord == null) {
- return "unknown";
- }
- Resource res = (Resource) listGridRecord.getAttributeAsObject(Field.RESOURCE);
- String url = LinkManager.getResourceLink(res.getId());
- // TODO disambiguate the resource name
- return SeleniumUtility.getLocatableHref(url, res.getName(), null);
+ String url = LinkManager
+ .getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+ return SeleniumUtility.getLocatableHref(url, o.toString(), null);
}
});
- fields.add(resourceField);
+ resourceNameField.setShowHover(true);
+ resourceNameField.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+ }
+ });
+ fields.add(resourceNameField);
+
+ ListGridField ancestryField = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, MSG.common_title_ancestry());
+ ancestryField.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return listGridRecord.getAttributeAsString(AncestryUtil.RESOURCE_ANCESTRY_VALUE);
+ }
+ });
+ ancestryField.setShowHover(true);
+ ancestryField.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getAncestryHoverHTML(listGridRecord, 0);
+ }
+ });
+ fields.add(ancestryField);
idField.setWidth("10%");
- submittedTimeField.setWidth("20%");
- completedTimeField.setWidth("20%");
+ submittedTimeField.setWidth(150);
+ completedTimeField.setWidth(150);
statusField.setWidth("10%");
subjectField.setWidth("10%");
updateTypeField.setWidth("10%");
- resourceField.setWidth("*");
+ resourceNameField.setWidth("30%");
+ ancestryField.setWidth("*");
} else {
idField.setWidth("10%");
submittedTimeField.setWidth("20%");
@@ -264,8 +282,6 @@ public abstract class AbstractConfigurationHistoryDataSource<T extends AbstractR
public ListGridRecord copyValues(T from) {
ListGridRecord record = new ListGridRecord();
record.setAttribute(Field.ID, from.getId());
- record.setAttribute(Field.RESOURCE, from.getResource());
- record.setAttribute(Field.RESOURCE_TYPE_ID, from.getResource().getResourceType().getId());
record.setAttribute(Field.SUBJECT, from.getSubjectName());
record.setAttribute(Field.STATUS, from.getStatus().name());
record.setAttribute(Field.CONFIGURATION, from.getConfiguration());
@@ -280,6 +296,14 @@ public abstract class AbstractConfigurationHistoryDataSource<T extends AbstractR
record.setAttribute(Field.GROUP_CONFIG_UPDATE_ID, from.getAbstractGroupConfigurationUpdate().getId());
record.setAttribute(Field.GROUP_ID, from.getAbstractGroupConfigurationUpdate().getGroup().getId()); // note group must be eagerly loaded here
}
+
+ // for ancestry handling
+ Resource resource = from.getResource();
+ record.setAttribute(AncestryUtil.RESOURCE_ID, resource.getId());
+ record.setAttribute(AncestryUtil.RESOURCE_NAME, resource.getName());
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY, resource.getAncestry());
+ record.setAttribute(AncestryUtil.RESOURCE_TYPE_ID, resource.getResourceType().getId());
+
record.setAttribute(Field.OBJECT, from);
return record;
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java
index 47dc9a0..2b0709e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ConfigurationHistoryDataSource.java
@@ -18,19 +18,28 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configuration;
+import java.util.HashSet;
+import java.util.Map;
+
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
+import com.smartgwt.client.data.Record;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
/**
* A data source that loads information about all the configuration changes that happened
@@ -82,10 +91,42 @@ public class ConfigurationHistoryDataSource extends AbstractConfigurationHistory
public void onSuccess(final PageList<ResourceConfigurationUpdate> result) {
final ListGridRecord[] records = buildRecords(result);
if (resourceId == null) {
- response.setData(records);
- response.setTotalRows(result.getTotalSize());
- processResponse(request.getRequestId(), response);
- return; // we can finish now, we don't need any additional information
+ HashSet<Integer> typesSet = new HashSet<Integer>();
+ HashSet<String> ancestries = new HashSet<String>();
+ for (ResourceConfigurationUpdate update : result) {
+ Resource resource = update.getResource();
+ typesSet.add(resource.getResourceType().getId());
+ ancestries.add(resource.getAncestry());
+ }
+
+ // In addition to the types of the result resources, get the types of their ancestry
+ typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
+
+ ResourceTypeRepository typeRepo = ResourceTypeRepository.Cache.getInstance();
+ typeRepo.getResourceTypes(typesSet.toArray(new Integer[typesSet.size()]),
+ new TypesLoadedCallback() {
+ @Override
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ // Smartgwt has issues storing a Map as a ListGridRecord attribute. Wrap it in a pojo.
+ AncestryUtil.MapWrapper typesWrapper = new AncestryUtil.MapWrapper(types);
+
+ Record[] records = buildRecords(result);
+ for (Record record : records) {
+ // To avoid a lot of unnecessary String construction, be lazy about building ancestry hover text.
+ // Store the types map off the records so we can build a detailed hover string as needed.
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_TYPES, typesWrapper);
+
+ // Build the decoded ancestry Strings now for display
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_VALUE, AncestryUtil
+ .getAncestryValue(record));
+ }
+ response.setData(records);
+ response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ processResponse(request.getRequestId(), response);
+ }
+ });
+
+ return;
}
// we are obtaining a single resource's history items. Let's find out which is
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationHistoryDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationHistoryDataSource.java
index b6831a5..4918dff 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationHistoryDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/inventory/PluginConfigurationHistoryDataSource.java
@@ -18,20 +18,29 @@
*/
package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.inventory;
+import java.util.HashSet;
+import java.util.Map;
+
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
+import com.smartgwt.client.data.Record;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.criteria.PluginConfigurationUpdateCriteria;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.LinkManager;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
import org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.configuration.AbstractConfigurationHistoryDataSource;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
/**
* A data source that loads information about all the plugin configuration changes that happened
@@ -83,10 +92,42 @@ public class PluginConfigurationHistoryDataSource extends
public void onSuccess(final PageList<PluginConfigurationUpdate> result) {
final ListGridRecord[] records = buildRecords(result);
if (resourceId == null) {
- response.setData(records);
- response.setTotalRows(result.getTotalSize());
- processResponse(request.getRequestId(), response);
- return; // we can finish now, we don't need any additional information
+ HashSet<Integer> typesSet = new HashSet<Integer>();
+ HashSet<String> ancestries = new HashSet<String>();
+ for (PluginConfigurationUpdate update : result) {
+ Resource resource = update.getResource();
+ typesSet.add(resource.getResourceType().getId());
+ ancestries.add(resource.getAncestry());
+ }
+
+ // In addition to the types of the result resources, get the types of their ancestry
+ typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
+
+ ResourceTypeRepository typeRepo = ResourceTypeRepository.Cache.getInstance();
+ typeRepo.getResourceTypes(typesSet.toArray(new Integer[typesSet.size()]),
+ new TypesLoadedCallback() {
+ @Override
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ // Smartgwt has issues storing a Map as a ListGridRecord attribute. Wrap it in a pojo.
+ AncestryUtil.MapWrapper typesWrapper = new AncestryUtil.MapWrapper(types);
+
+ Record[] records = buildRecords(result);
+ for (Record record : records) {
+ // To avoid a lot of unnecessary String construction, be lazy about building ancestry hover text.
+ // Store the types map off the records so we can build a detailed hover string as needed.
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_TYPES, typesWrapper);
+
+ // Build the decoded ancestry Strings now for display
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_VALUE, AncestryUtil
+ .getAncestryValue(record));
+ }
+ response.setData(records);
+ response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ processResponse(request.getRequestId(), response);
+ }
+ });
+
+ return;
}
// we are obtaining a single resource's history items. Let's find out which is
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ConfigurationGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ConfigurationGWTServiceImpl.java
index 336206b..4e551ed 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ConfigurationGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ConfigurationGWTServiceImpl.java
@@ -16,6 +16,7 @@ import org.rhq.core.domain.criteria.GroupPluginConfigurationUpdateCriteria;
import org.rhq.core.domain.criteria.GroupResourceConfigurationUpdateCriteria;
import org.rhq.core.domain.criteria.PluginConfigurationUpdateCriteria;
import org.rhq.core.domain.criteria.ResourceConfigurationUpdateCriteria;
+import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.composite.DisambiguationReport;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.util.PageControl;
@@ -155,9 +156,20 @@ public class ConfigurationGWTServiceImpl extends AbstractGWTServiceImpl implemen
public PageList<ResourceConfigurationUpdate> findResourceConfigurationUpdates(Integer resourceId, Long beginDate,
Long endDate, boolean suppressOldest, PageControl pc) throws RuntimeException {
try {
- PageList<ResourceConfigurationUpdate> result = configurationManager.findResourceConfigurationUpdates(
+ PageList<ResourceConfigurationUpdate> updates = configurationManager.findResourceConfigurationUpdates(
getSessionSubject(), resourceId, beginDate, endDate, suppressOldest, pc);
- return SerialUtility.prepare(result, "ConfigurationService.findResourceConfigurationUpdates");
+ if (!updates.isEmpty()) {
+ List<Resource> resources = new ArrayList<Resource>(updates.size());
+ for (ResourceConfigurationUpdate update : updates) {
+ Resource res = update.getResource();
+ if (null != res) {
+ resources.add(res);
+ }
+ }
+ ObjectFilter.filterFieldsInCollection(resources, ResourceGWTServiceImpl.importantFieldsSet);
+ }
+
+ return SerialUtility.prepare(updates, "ConfigurationService.findResourceConfigurationUpdates");
} catch (Throwable t) {
throw new RuntimeException(ThrowableUtil.getAllMessages(t));
}
@@ -193,6 +205,17 @@ public class ConfigurationGWTServiceImpl extends AbstractGWTServiceImpl implemen
try {
PageList<ResourceConfigurationUpdate> updates = configurationManager
.findResourceConfigurationUpdatesByCriteria(getSessionSubject(), criteria);
+ if (!updates.isEmpty()) {
+ List<Resource> resources = new ArrayList<Resource>(updates.size());
+ for (ResourceConfigurationUpdate update : updates) {
+ Resource res = update.getResource();
+ if (null != res) {
+ resources.add(res);
+ }
+ }
+ ObjectFilter.filterFieldsInCollection(resources, ResourceGWTServiceImpl.importantFieldsSet);
+ }
+
return SerialUtility.prepare(updates, "ConfigurationService.findResourceConfigurationUpdatesByCriteria");
} catch (Throwable t) {
throw new RuntimeException(ThrowableUtil.getAllMessages(t));
@@ -205,6 +228,17 @@ public class ConfigurationGWTServiceImpl extends AbstractGWTServiceImpl implemen
try {
PageList<PluginConfigurationUpdate> updates = configurationManager
.findPluginConfigurationUpdatesByCriteria(getSessionSubject(), criteria);
+ if (!updates.isEmpty()) {
+ List<Resource> resources = new ArrayList<Resource>(updates.size());
+ for (PluginConfigurationUpdate update : updates) {
+ Resource res = update.getResource();
+ if (null != res) {
+ resources.add(res);
+ }
+ }
+ ObjectFilter.filterFieldsInCollection(resources, ResourceGWTServiceImpl.importantFieldsSet);
+ }
+
return SerialUtility.prepare(updates, "ConfigurationService.findPluginConfigurationUpdatesByCriteria");
} catch (Throwable t) {
throw new RuntimeException(ThrowableUtil.getAllMessages(t));
13 years, 3 months
[rhq] modules/enterprise
by mazz
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java | 54 +++++-----
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java | 9 +
2 files changed, 39 insertions(+), 24 deletions(-)
New commits:
commit 29960f759d35ace3e8bac334ee49abafaefd2055
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Mar 15 00:59:43 2011 -0400
BZ 664126 - concurrent calls to setResourceError need separate transactions
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index 8c0e7d6..384104a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -1855,26 +1855,16 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
}
public void addResourceError(ResourceError resourceError) {
- Subject overlord = subjectManager.getOverlord();
- Resource resource;
- try {
- resource = getResourceById(overlord, resourceError.getResource().getId());
- } catch (ResourceNotFoundException rnfe) {
- throw new ResourceNotFoundException("Resource error an unknown Resource id: " + resourceError);
- }
+ ResourceErrorType resourceErrorType = resourceError.getErrorType();
- if (resourceError.getErrorType() == ResourceErrorType.INVALID_PLUGIN_CONFIGURATION
- || resourceError.getErrorType() == ResourceErrorType.AVAILABILITY_CHECK
- || resourceError.getErrorType() == ResourceErrorType.UPGRADE) {
+ if (resourceErrorType == ResourceErrorType.INVALID_PLUGIN_CONFIGURATION
+ || resourceErrorType == ResourceErrorType.AVAILABILITY_CHECK
+ || resourceErrorType == ResourceErrorType.UPGRADE) {
// there should be at most one invalid plugin configuration error, availability check
// or upgrade error per resource, so delete any currently existing ones before we add this new one
- List<ResourceError> doomedErrors = resource.getResourceErrors(resourceError.getErrorType());
-
- // there should only ever be at most 1, but loop through the list just in case something got screwed up
- // and there ended up more than 1 associated with the resource.
- for (ResourceError doomedError : doomedErrors) {
- entityManager.remove(doomedError);
- }
+ Subject overlord = subjectManager.getOverlord();
+ int resourceId = resourceError.getResource().getId();
+ resourceManager.clearResourceConfigErrorByType(overlord, resourceId, resourceErrorType);
}
entityManager.persist(resourceError);
@@ -1882,24 +1872,40 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
return;
}
- public void clearResourceConfigError(int resourceId) {
- // TODO Add subject permissions to this method
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public int clearResourceConfigErrorByType(Subject subject, int resourceId, ResourceErrorType resourceErrorType) {
+
+ if (!authorizationManager.canViewResource(subject, resourceId)) {
+ throw new PermissionException("Cannot delete resource errors of type [" + resourceErrorType + "]. User ["
+ + subject.getName() + "] does not have permission to operate on resource ID [" + resourceId + "].");
+ }
Query q = entityManager
- .createQuery("delete from ResourceError e where e.resource.id = :resourceId and e.errorType = :type");
+ .createQuery("DELETE FROM ResourceError e WHERE e.resource.id = :resourceId AND e.errorType = :type");
q.setParameter("resourceId", resourceId);
- q.setParameter("type", ResourceErrorType.INVALID_PLUGIN_CONFIGURATION);
+ q.setParameter("type", resourceErrorType);
int updates = q.executeUpdate();
+ return updates;
+ }
+
+ public void clearResourceConfigError(int resourceId) {
+ // TODO change sig to get user passed in, rather than using overlord/assuming user is authz'ed
+ Subject s = subjectManager.getOverlord();
+
+ // make a direct local call - no need to go through the ByType method's REQUIRES_NEW interface here
+ int cleared = clearResourceConfigErrorByType(s, resourceId, ResourceErrorType.INVALID_PLUGIN_CONFIGURATION);
- if (updates > 1) {
- log.error("Resource [" + resourceId + "] has [" + updates
- + "] INVALID_PLUGIN_CONFIGURATION ResourceError associated with it.");
+ if (cleared > 1) {
+ log.warn("Resource [" + resourceId + "] had [" + cleared
+ + "] INVALID_PLUGIN_CONFIGURATION ResourceErrors associated with it.");
}
+ return;
}
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void deleteResourceError(Subject user, int resourceErrorId) {
ResourceError error = entityManager.find(ResourceError.class, resourceErrorId);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
index 4eba088..02b0266 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
@@ -395,6 +395,15 @@ public interface ResourceManagerLocal {
void clearResourceConfigError(int resourceId);
/**
+ * Clears errors of the given type.
+ * @param subject the user that is making the request
+ * @param resourceId id of the resource
+ * @param resourceErrorType type of error to clear
+ * @return the number of errors that were cleared
+ */
+ int clearResourceConfigErrorByType(Subject subject, int resourceId, ResourceErrorType resourceErrorType);
+
+ /**
* Returns the platform Resource associated with the specified Agent.
*
* @param agent an Agent
13 years, 3 months
[rhq] modules/plugins
by mazz
modules/plugins/platform/src/main/java/org/rhq/plugins/platform/WindowsPlatformComponent.java | 25 +-
modules/plugins/platform/src/main/java/org/rhq/plugins/platform/win/Win32EventLogDelegate.java | 122 +++++-----
2 files changed, 82 insertions(+), 65 deletions(-)
New commits:
commit be007b5c9e336e2401b9fe10a8361d918fe3b31c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 14 23:44:07 2011 -0400
make win32 event log collection more fault tolerant - catch exceptions better and don't try to do things with event logs when we aren't collecting events (i.e. do null checks)
diff --git a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/WindowsPlatformComponent.java b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/WindowsPlatformComponent.java
index 28ed7e7..60f451a 100644
--- a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/WindowsPlatformComponent.java
+++ b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/WindowsPlatformComponent.java
@@ -27,11 +27,14 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.transfer.DeployPackageStep;
+import org.rhq.core.domain.content.transfer.DeployPackagesResponse;
import org.rhq.core.domain.content.transfer.RemovePackagesResponse;
import org.rhq.core.domain.content.transfer.ResourcePackageDetails;
import org.rhq.core.pluginapi.content.ContentFacet;
@@ -44,6 +47,8 @@ import org.rhq.plugins.platform.win.WindowsSoftwareDelegate;
* @author Greg Hinkle
*/
public class WindowsPlatformComponent extends PlatformComponent implements ContentFacet {
+ private final Log log = LogFactory.getLog(WindowsPlatformComponent.class);
+
private Win32EventLogDelegate eventLogDelegate;
private boolean enableContentDiscovery = false;
@@ -51,9 +56,21 @@ public class WindowsPlatformComponent extends PlatformComponent implements Conte
super.start(context);
Configuration pluginConfiguration = context.getPluginConfiguration();
if (pluginConfiguration.getSimple("eventTrackingEnabled").getBooleanValue()) {
- eventLogDelegate = new Win32EventLogDelegate(pluginConfiguration);
- eventLogDelegate.open();
- context.getEventContext().registerEventPoller(eventLogDelegate, 60);
+ try {
+ eventLogDelegate = new Win32EventLogDelegate(pluginConfiguration);
+ eventLogDelegate.open();
+ context.getEventContext().registerEventPoller(eventLogDelegate, 60);
+ } catch (Throwable t) {
+ log.error("Failed to start the event logger. Will not be able to capture Windows events", t);
+ if (eventLogDelegate != null) {
+ try {
+ eventLogDelegate.close();
+ } catch (Throwable t2) {
+ } finally {
+ eventLogDelegate = null;
+ }
+ }
+ }
}
PropertySimple contentProp = pluginConfiguration.getSimple("enableContentDiscovery");
diff --git a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/win/Win32EventLogDelegate.java b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/win/Win32EventLogDelegate.java
index 9d6188f..62e217f 100644
--- a/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/win/Win32EventLogDelegate.java
+++ b/modules/plugins/platform/src/main/java/org/rhq/plugins/platform/win/Win32EventLogDelegate.java
@@ -1,25 +1,25 @@
- /*
- * RHQ Management Platform
- * Copyright (C) 2005-2008 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, version 2, as
- * published by the Free Software Foundation, and/or the GNU Lesser
- * General Public License, version 2.1, also 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 and the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the GNU Lesser 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.
- */
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 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, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also 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 and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser 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.plugins.platform.win;
import java.util.HashSet;
@@ -31,7 +31,6 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.win32.EventLog;
import org.hyperic.sigar.win32.EventLogRecord;
-import org.hyperic.sigar.win32.Win32Exception;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,36 +84,35 @@ public class Win32EventLogDelegate implements EventPoller {
eventLogs = new EventLog[logNames.length];
lastCollectedEventId = new int[logNames.length];
-
- for (int i = 0; (i < logNames.length); ++i) {
- eventLogs[i] = new EventLog();
- }
}
public void open() {
- try {
- int i = 0;
- for (String logName : logNames) {
-
- eventLogs[i].open(logName);
-
- // note, the first processed event will be the next one generated, this one
- // was generated in the past, prior to this call to open().
- lastCollectedEventId[i] = eventLogs[i].getNewestRecord();
+ for (int i = 0; i < eventLogs.length; i++) {
+ try {
+ if (eventLogs[i] == null) {
+ eventLogs[i] = new EventLog();
+ eventLogs[i].open(logNames[i]);
- i++;
+ // note, the first processed event will be the next one generated, this one
+ // was generated in the past, prior to this call to open().
+ lastCollectedEventId[i] = eventLogs[i].getNewestRecord();
+ }
+ } catch (Exception e) {
+ log.warn("Failed to open Windows Event Log [" + logNames[i] + "]; will not collect its events", e);
+ eventLogs[i] = null;
}
- } catch (Win32Exception e) {
- log.warn("Failed to open Windows Event Log, log tracking will not return events", e);
}
}
public void close() {
- for (EventLog eventLog : eventLogs) {
+ for (int i = 0; i < eventLogs.length; i++) {
try {
- eventLog.close();
- } catch (Win32Exception e) {
- log.warn("Failed to close Windows Event Log", e);
+ if (eventLogs[i] != null) {
+ eventLogs[i].close();
+ eventLogs[i] = null;
+ }
+ } catch (Exception e) {
+ log.warn("Failed to close Windows Event Log [" + logNames[i] + "]", e);
}
}
}
@@ -124,41 +122,43 @@ public class Win32EventLogDelegate implements EventPoller {
Set<Event> convertedEvents = null;
for (int i = 0; i < eventLogs.length; i++) {
try {
- int newest = eventLogs[i].getNewestRecord();
- if (newest > lastCollectedEventId[i]) {
- for (int eventId = lastCollectedEventId[i] + 1; eventId <= newest; eventId++) {
- eventsChecked++;
+ if (eventLogs[i] != null) {
+ int newest = eventLogs[i].getNewestRecord();
+ if (newest > lastCollectedEventId[i]) {
+ for (int eventId = lastCollectedEventId[i] + 1; eventId <= newest; eventId++) {
+ eventsChecked++;
- EventLogRecord event = eventLogs[i].read(eventId);
- Event convertedEvent = handleEvent(event);
+ EventLogRecord event = eventLogs[i].read(eventId);
+ Event convertedEvent = handleEvent(event);
- if (null != convertedEvent) {
- if (null == convertedEvents) {
- convertedEvents = new HashSet<Event>();
- }
+ if (null != convertedEvent) {
+ if (null == convertedEvents) {
+ convertedEvents = new HashSet<Event>();
+ }
- convertedEvents.add(convertedEvent);
+ convertedEvents.add(convertedEvent);
+ }
}
+ lastCollectedEventId[i] = newest;
}
- lastCollectedEventId[i] = newest;
}
- } catch (Win32Exception e) {
- log.info("An error occurred while reading the Windows Event Log", e);
+ } catch (Exception e) {
+ log.info("An error occurred while reading the Windows Event Log [" + logNames[i] + "]", e);
}
}
return convertedEvents;
}
public Event handleEvent(EventLogRecord event) {
- eventsChecked++;
-
if (regularExpression != null) {
- if (!regularExpression.matcher(event.getMessage()).find())
+ if (!regularExpression.matcher(event.getMessage()).find()) {
return null;
+ }
}
- if (!convertSeverity(event.getEventType()).isAtLeastAsSevereAs(minimumSeverity))
+ if (!convertSeverity(event.getEventType()).isAtLeastAsSevereAs(minimumSeverity)) {
return null;
+ }
Event convertedEvent = new Event(EVENT_TYPE, event.getLogName(), event.getTimeGenerated() * 1000,
convertSeverity(event.getEventType()), event.getMessage());
13 years, 3 months
[rhq] modules/enterprise
by mazz
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java | 16 ++++++----
1 file changed, 10 insertions(+), 6 deletions(-)
New commits:
commit b7c4250fd086b7c3a2e7a883fc884c9d9a82f6c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 14 17:51:56 2011 -0400
i see this fail one in a blue moon and still can't figure out why. I tried to replicate and step thru with debugger, and it works.
dump the resource error entity that failed to persist - maybe that can help out next time this happens
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java
index 65f8c7c..9160eb4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryServerServiceImpl.java
@@ -41,7 +41,6 @@ import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceError;
-import org.rhq.core.domain.resource.ResourceUpgradeReport;
import org.rhq.core.util.collection.ArrayUtils;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.server.alert.AlertDefinitionCreationException;
@@ -66,8 +65,8 @@ public class DiscoveryServerServiceImpl implements DiscoveryServerService {
/**
* @see DiscoveryServerService#mergeInventoryReport(InventoryReport)
*/
- public ResourceSyncInfo mergeInventoryReport(InventoryReport report)
- throws InvalidInventoryReportException, StaleTypeException {
+ public ResourceSyncInfo mergeInventoryReport(InventoryReport report) throws InvalidInventoryReportException,
+ StaleTypeException {
long start = System.currentTimeMillis();
DiscoveryBossLocal discoveryBoss = LookupUtil.getDiscoveryBoss();
ResourceSyncInfo syncInfo;
@@ -163,8 +162,13 @@ public class DiscoveryServerServiceImpl implements DiscoveryServerService {
}
public void setResourceError(ResourceError resourceError) {
- ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
- resourceManager.addResourceError(resourceError);
+ try {
+ ResourceManagerLocal resourceManager = LookupUtil.getResourceManager();
+ resourceManager.addResourceError(resourceError);
+ } catch (RuntimeException re) {
+ log.error("Failed to persist resource error: " + resourceError);
+ throw re;
+ }
}
public void clearResourceConfigError(int resourceId) {
@@ -186,7 +190,7 @@ public class DiscoveryServerServiceImpl implements DiscoveryServerService {
DiscoveryBossLocal discoveryBoss = LookupUtil.getDiscoveryBoss();
return discoveryBoss.upgradeResources(upgradeRequests);
}
-
+
private static Resource convertToPojoResource(Resource resource, boolean includeDescendants) {
Resource pojoResource = new Resource(resource.getId());
pojoResource.setUuid(resource.getUuid());
13 years, 3 months
[rhq] modules/enterprise
by mazz
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java | 7 +++++++
1 file changed, 7 insertions(+)
New commits:
commit 73c923e8ea8e3b016138d06a027189393e8f2684
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 14 17:14:17 2011 -0400
the operation history list is not sorted and sometimes the ordering is ad-hoc.
want to see the last executed op at the top of the list and sorted descendingly
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java
index edb9ff7..50593ec 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java
@@ -26,8 +26,10 @@ import com.google.gwt.i18n.client.DateTimeFormat;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.Record;
+import com.smartgwt.client.data.SortSpecifier;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.Overflow;
+import com.smartgwt.client.types.SortDirection;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickHandler;
@@ -76,6 +78,11 @@ public abstract class AbstractOperationHistoryListView<T extends AbstractOperati
List<ListGridField> fields = createFields();
setListGridFields(fields.toArray(new ListGridField[fields.size()]));
+ // explicitly sort on started time so the user can see the last operation at the top and is sorted descendingly
+ SortSpecifier sortspec = new SortSpecifier(AbstractOperationHistoryDataSource.Field.STARTED_TIME,
+ SortDirection.DESCENDING);
+ getListGrid().setSort(new SortSpecifier[] { sortspec });
+
addTableAction(extendLocatorId("Delete"), MSG.common_button_delete(), getDeleteConfirmMessage(),
new TableAction() {
public boolean isEnabled(ListGridRecord[] selection) {
13 years, 3 months
[rhq] modules/enterprise
by Jay Shaughnessy
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java | 3
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsDataSource.java | 10
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/AlertDefinitionReportView.java | 108 ++++++++--
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java | 13 +
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 1
5 files changed, 115 insertions(+), 20 deletions(-)
New commits:
commit acb761df457d4753ac4f9277a95831358110513d
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Mar 14 16:59:16 2011 -0400
Add Ancestry (Disambiguation) to Alert Def Subsystem View
- add Resource filtering to AlertDef criteria fetches
- eliminate a duplicate I18N property
-
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java
index db11bdd..4ef6e16 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java
@@ -164,8 +164,7 @@ public class AlertDataSource extends RPCDataSource<Alert> {
fields.add(statusField);
if (this.entityContext.type != EntityContext.Type.Resource) {
- ListGridField resourceNameField = new ListGridField(AncestryUtil.RESOURCE_NAME, MSG
- .view_alerts_field_resource());
+ ListGridField resourceNameField = new ListGridField(AncestryUtil.RESOURCE_NAME, MSG.common_title_resource());
resourceNameField.setCellFormatter(new CellFormatter() {
public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
String url = LinkManager
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsDataSource.java
index d073ab1..ee50f73 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsDataSource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/definitions/AbstractAlertDefinitionsDataSource.java
@@ -195,12 +195,18 @@ public abstract class AbstractAlertDefinitionsDataSource extends RPCDataSource<A
}
public void onSuccess(PageList<AlertDefinition> result) {
- response.setData(buildRecords(result));
- processResponse(request.getRequestId(), response);
+ dataRetrieved(result, response, request);
}
});
}
+ protected void dataRetrieved(final PageList<AlertDefinition> result, final DSResponse response,
+ final DSRequest request) {
+
+ response.setData(buildRecords(result));
+ processResponse(request.getRequestId(), response);
+ }
+
protected abstract AlertDefinitionCriteria getCriteria(DSRequest request);
/**
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/AlertDefinitionReportView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/AlertDefinitionReportView.java
index 5d05431..fcd9279 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/AlertDefinitionReportView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/AlertDefinitionReportView.java
@@ -1,10 +1,13 @@
package org.rhq.enterprise.gui.coregui.client.report;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
+import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSourceField;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.fields.DataSourceTextField;
@@ -22,6 +25,7 @@ import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
@@ -30,6 +34,10 @@ import org.rhq.enterprise.gui.coregui.client.alert.definitions.AbstractAlertDefi
import org.rhq.enterprise.gui.coregui.client.components.table.Table;
import org.rhq.enterprise.gui.coregui.client.components.view.ViewName;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository;
+import org.rhq.enterprise.gui.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback;
+import org.rhq.enterprise.gui.coregui.client.util.selenium.SeleniumUtility;
/**
* A tabular report that shows alert definitions on all resources in inventory.
@@ -114,19 +122,6 @@ public class AlertDefinitionReportView extends Table<AlertDefinitionReportView.D
}
// add more columns
- ListGridField resourceField = new ListGridField(FIELD_RESOURCE, MSG.common_title_resource());
- resourceField.setCellFormatter(new CellFormatter() {
- @Override
- public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
- AlertDefinition alertDef = copyValues(record);
- Resource resource = alertDef.getResource();
- String link = LinkManager.getResourceLink(resource.getId());
- // TODO: need disambiguation
- return "<a href=\"" + link + "\">" + resource.getName() + "</a>";
- }
- });
- fields.add(resourceField);
-
ListGridField parentField = new ListGridField(FIELD_PARENT, MSG.view_alerts_field_parent());
parentField.setWidth(100);
parentField.setShowHover(true);
@@ -182,9 +177,40 @@ public class AlertDefinitionReportView extends Table<AlertDefinitionReportView.D
}
}
});
-
fields.add(parentField);
+ ListGridField resourceField = new ListGridField(FIELD_RESOURCE, MSG.common_title_resource());
+ resourceField.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
+ String url = LinkManager
+ .getResourceLink(listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID));
+ return SeleniumUtility.getLocatableHref(url, o.toString(), null);
+ }
+ });
+ resourceField.setShowHover(true);
+ resourceField.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getResourceHoverHTML(listGridRecord, 0);
+ }
+ });
+ fields.add(resourceField);
+
+ ListGridField ancestryField = new ListGridField(AncestryUtil.RESOURCE_ANCESTRY, MSG.common_title_ancestry());
+ ancestryField.setCellFormatter(new CellFormatter() {
+ public String format(Object o, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return listGridRecord.getAttributeAsString(AncestryUtil.RESOURCE_ANCESTRY_VALUE);
+ }
+ });
+ ancestryField.setShowHover(true);
+ ancestryField.setHoverCustomizer(new HoverCustomizer() {
+
+ public String hoverHTML(Object value, ListGridRecord listGridRecord, int rowNum, int colNum) {
+ return AncestryUtil.getAncestryHoverHTML(listGridRecord, 0);
+ }
+ });
+ fields.add(ancestryField);
+
return fields;
}
@@ -193,8 +219,9 @@ public class AlertDefinitionReportView extends Table<AlertDefinitionReportView.D
// in order to support sorting our list grid on the parent and resource columns,
// we have to assign these to something that is sortable
ListGridRecord record = super.copyValues(from);
+ Resource resource = from.getResource();
- record.setAttribute(FIELD_RESOURCE, from.getResource().getName());
+ record.setAttribute(FIELD_RESOURCE, resource.getName());
Integer parentId = from.getParentId(); // a valid non-zero number means the alert def came from a template
AlertDefinition groupAlertDefinition = from.getGroupAlertDefinition();
@@ -205,6 +232,12 @@ public class AlertDefinitionReportView extends Table<AlertDefinitionReportView.D
record.setAttribute(FIELD_PARENT, "<b>" + MSG.view_alert_definition_for_group() + "</b>");
}
+ // for ancestry handling
+ record.setAttribute(AncestryUtil.RESOURCE_ID, resource.getId());
+ record.setAttribute(AncestryUtil.RESOURCE_NAME, resource.getName());
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY, resource.getAncestry());
+ record.setAttribute(AncestryUtil.RESOURCE_TYPE_ID, resource.getResourceType().getId());
+
return record;
}
@@ -229,5 +262,50 @@ public class AlertDefinitionReportView extends Table<AlertDefinitionReportView.D
return fields;
}
+
+ /**
+ * Additional processing to support a cross-resource view)
+ * @param result
+ * @param response
+ * @param request
+ */
+ protected void dataRetrieved(final PageList<AlertDefinition> result, final DSResponse response,
+ final DSRequest request) {
+ HashSet<Integer> typesSet = new HashSet<Integer>();
+ HashSet<String> ancestries = new HashSet<String>();
+ for (AlertDefinition alertDefinition : result) {
+ Resource resource = alertDefinition.getResource();
+ if (null != resource) {
+ typesSet.add(resource.getResourceType().getId());
+ ancestries.add(resource.getAncestry());
+ }
+ }
+
+ // In addition to the types of the result resources, get the types of their ancestry
+ typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries));
+
+ ResourceTypeRepository typeRepo = ResourceTypeRepository.Cache.getInstance();
+ typeRepo.getResourceTypes(typesSet.toArray(new Integer[typesSet.size()]), new TypesLoadedCallback() {
+
+ public void onTypesLoaded(Map<Integer, ResourceType> types) {
+ // Smartgwt has issues storing a Map as a ListGridRecord attribute. Wrap it in a pojo.
+ AncestryUtil.MapWrapper typesWrapper = new AncestryUtil.MapWrapper(types);
+
+ Record[] records = buildRecords(result);
+ for (Record record : records) {
+ // To avoid a lot of unnecessary String construction, be lazy about building ancestry hover text.
+ // Store the types map off the records so we can build a detailed hover string as needed.
+ record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_TYPES, typesWrapper);
+
+ // Build the decoded ancestry Strings now for display
+ record
+ .setAttribute(AncestryUtil.RESOURCE_ANCESTRY_VALUE, AncestryUtil.getAncestryValue(record));
+ }
+ response.setData(records);
+ response.setTotalRows(result.getTotalSize()); // for paging to work we have to specify size of full result set
+ processResponse(request.getRequestId(), response);
+ }
+ });
+ }
}
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
index 3ed01c2..6f15250 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AlertDefinitionGWTServiceImpl.java
@@ -18,12 +18,14 @@
*/
package org.rhq.enterprise.gui.coregui.server.gwt;
+import java.util.ArrayList;
import java.util.List;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.alert.notification.AlertNotification;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
+import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.gui.coregui.client.gwt.AlertDefinitionGWTService;
@@ -44,6 +46,17 @@ public class AlertDefinitionGWTServiceImpl extends AbstractGWTServiceImpl implem
try {
PageList<AlertDefinition> results = this.alertDefManager.findAlertDefinitionsByCriteria(
getSessionSubject(), criteria);
+ if (!results.isEmpty()) {
+ List<Resource> resources = new ArrayList<Resource>(results.size());
+ for (AlertDefinition alertDefinition : results) {
+ Resource res = alertDefinition.getResource();
+ if (null != res) {
+ resources.add(res);
+ }
+ }
+ ObjectFilter.filterFieldsInCollection(resources, ResourceGWTServiceImpl.importantFieldsSet);
+ }
+
return SerialUtility.prepare(results, "findAlertDefinitionsByCriteria");
} catch (Throwable t) {
throw new RuntimeException(ThrowableUtil.getAllMessages(t));
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index a6b9716..e8066f3 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -882,7 +882,6 @@ view_alerts_field_condition_text = Condition Text
view_alerts_field_condition_text_none = No Conditions
view_alerts_field_condition_text_many = Multiple Conditions
view_alerts_field_condition_value = Condition Value
-view_alerts_field_resource = Resource
view_alerts_field_priority = Priority
view_alerts_field_parent = Parent
view_alerts_field_protected = Protected
13 years, 3 months
[rhq] 3 commits - modules/enterprise modules/plugins pom.xml
by John Sanda
modules/enterprise/agent/src/etc/rhq-agent-wrapper-ec2 | 122 ++++++
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagement.java | 4
modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagementMBean.java | 2
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java | 8
modules/enterprise/server/container/pom.xml | 2
modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml | 3
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerBean.java | 15
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerLocal.java | 9
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/SyncEndpointAddressException.java | 20 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java | 10
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java | 1
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java | 9
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java | 70 +++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java | 9
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulScheduledJobInvocationContext.java | 65 +++
modules/enterprise/server/plugins/cloud/pom.xml | 146 +++++++
modules/enterprise/server/plugins/cloud/src/main/java/org/rhq/enterprise/server/plugins/cloud/CloudServerPluginComponent.java | 193 ++++++++++
modules/enterprise/server/plugins/cloud/src/main/resources/META-INF/rhq-serverplugin.xml | 57 ++
modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentServerComponent.java | 3
modules/plugins/rhq-agent/src/main/resources/META-INF/rhq-plugin.xml | 11
pom.xml | 12
21 files changed, 770 insertions(+), 1 deletion(-)
New commits:
commit fcd0a45565086410ecfbc443b7312743a6bb017d
Merge: 0f4f948 0846d35
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Mar 14 15:30:51 2011 -0400
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 0f4f94855bca6fae56f83919d378c8168e648410
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Mar 14 15:14:31 2011 -0400
Updating version of cloud server plugin
diff --git a/modules/enterprise/server/plugins/cloud/pom.xml b/modules/enterprise/server/plugins/cloud/pom.xml
index 8d10fcd..b66ad28 100644
--- a/modules/enterprise/server/plugins/cloud/pom.xml
+++ b/modules/enterprise/server/plugins/cloud/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.rhq</groupId>
<artifactId>rhq-enterprise-server-plugins-parent</artifactId>
- <version>3.0.1-SNAPSHOT</version>
+ <version>4.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
commit 332f77eb8450aed98d2c33935f47680b7d29e392
Author: John Sanda <jsanda(a)redhat.com>
Date: Mon Mar 14 15:09:53 2011 -0400
Squahshing 13 commits from ec2 branch
first commit message:
Adding new operation to rhq-agent plugin to update the server endpoint url
Invoking the switchToServer operation will result in the operation switching
over to the specified server. In an EC2 deployment, the server can invoke this
operation whenever its IP address has changed. Then the agent will have a valid
server endpoint url from which it can download its failover list.
second commit message:
Initial commit for rhq-agent-wrapper-ec2 script
This is a wrapper script for rhq-agent-wrapper.sh that additionally configures
the server endpoint url and will also set up the agent to run as a service.
third commit message:
Adding logic to check for and skip initialization if it has already run
The initialization function only needs to run the first time an agent
runs so that the server endpoint url can be specified. That url will be
supplied in the AMI's user-defined data. Also adding logic to force
initialization to run when specifying the <init> cmd line arg.
fourth commit message:
Adding ability for plugin jobs to persist data across invocations of jobs
Server plugin scheduled jobs previously had no mechanism provided by the plugin
framework for persisting data across invocations of the job. Quartz however
provides this capability when using a StatefulJob. Server plugin jobs run as
StatefulJob objects when they do not run concurrently. The only change needed
then was to expose a hook to the JobDataMap. A map has been added to
ScheduledJobInvocationContext which comes from the JobDataMap. Anything added
to this map by the server plugin job will be persisted from invocation of the
job to the next.
Initial commit for cloud plugin which at this point is just testing that
persisting job data works as expected.
fifth commit message:
Adding support for syncing the server endpoint url at start up.
The behavior is turned off by default. It can be enabled by setting
rhq.sync.endpoint-address=true
in rhq-server.properties. When this is enabled, the server at start up will
compare its endpoint address to the host name/address found on the host machine.
If they differ, the server endpoint address will be updated to the value found
on the host machine. This addresses the (first part of the problem of)
address/host name changes that will occur in EC2 when a server machine is
restarted.
sixth commit message:
Restricting plugins to storing only string in the job data
Quartz is already configured to only allow strings to be stored in the job data
map when a job is scheduled for concurrent execution. Restricting entries in
the map to strings is recommended to avoid class versioning errors that are
common during deserialization. ScheduledInvocationContext has been refactored
a bit so that the underlying map is no longer directly exposed. To edit values
in the map it now exposes get/put methods that help enforce and ensure only
strings are stored in the map. There is still a getProperties() method; however,
it returns a read-only view of the data map.
seventh commit message:
Updating plugin descriptor to make cloud plugin clustered
Also refactoring plugin to work with new methods in
ScheduledJobInvocationContext
eigth commit message:
Only allow job data to be persisted when the job is not marked concurrent
Adding logic such that persisting job data in the
ScheduledJobInvocationContext is only supported when the job is not
marked as concurrent. If the job is marked as concurrent, and the plugin
calls a method to access or update properties, an exception will be
thrown.
Also adding some javadocs to explain how/when persisting job data is
supported
ninth commmit message:
Fixing methods to throw the correct exception type
tenth commit message:
Adding logic to detect changed addresses
eleventh commit message:
Schedule the 'switchToServer' agent resource operation
twelth commit message:
Exposing address sync job as an operation that can be manually invoked.
This is a first code at this plugin operation. Some error handling needs
to be added along with some logging.
thirteenth commit message:
Adding logic to purge stale servers from the sync list
If a server has been taken down and removed from the system, then we
need to remove it from the list of servers we look at to see if their
addresses need to be synced.
Adding a bunch of debug logging.
Conflicts:
modules/plugins/rhq-agent/src/main/resources/META-INF/rhq-plugin.xml
diff --git a/modules/enterprise/agent/src/etc/rhq-agent-wrapper-ec2 b/modules/enterprise/agent/src/etc/rhq-agent-wrapper-ec2
new file mode 100755
index 0000000..3808ba0
--- /dev/null
+++ b/modules/enterprise/agent/src/etc/rhq-agent-wrapper-ec2
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+# =============================================================================
+# RHQ AGENT LINUX/EC2 Boot Script
+#
+# This script is a wrapper script for rhq-agent-wrapper.sh which is used to
+# start/stop the agent on LINUX/UNIX platforms. This script provides some
+# additional functionality for automatically configuring the agent in an EC2
+# environment.
+#
+# When the agent is started with this script, it will check to see if server
+# endpoint URL has been configured. If it finds that the agent has not already
+# been configured the script fetches paramerters specified as part of the AMIs
+# user-defined data, parses the parameters, looking for the jon.server.url
+# parameter. The rhq.agent.server.bind-address setting is then configured with
+# the parameter's value. If the jon.server.url parameter is not found, an error
+# message is logged and the agent will not be started.
+#
+# To force initialization or to re-initialize the agent run,
+#
+# $ rhq-agent-wrapper-ec2 init
+# =============================================================================
+
+RHQ_AGENT_HOME=/usr/share/rhq-agent-<VERSION>
+SCRIPT_NAME=rhq-wrapper-agent-ec2
+
+function load_user_data
+{
+ user_data_url="http://169.254.169.254/1.0/user-data/"
+ user_data_file="/tmp/user_data"
+
+ #curl $user_data_url > $user_data_file
+
+ user_data=`cat $user_data_file`
+}
+
+function parse_jon_server_url
+{
+ ORIG_IFS=$IFS
+ IFS=$','
+
+ read -rda params <<< $user_data
+
+ IFS=$ORIG_IFS
+
+ for param in $params
+ do
+ idx=`expr index $param =`
+ key=${param:0:idx - 1}
+
+ if [ $key = jon.server.url ]; then
+ jon_server_url=${param:idx}
+ return 0
+ fi
+ done
+}
+
+function init
+{
+ force_init=$1
+ default_prefs=~/.java/.userPrefs/rhq-agent/default/prefs.xml
+
+ if [ -s $default_prefs ] && [ "force" != $force_init ]; then
+ echo "Default configuration found at $default_prefs. Skipping " \
+ "configuration. Run $SCRIPT_NAME <init> to force configuration " \
+ "of server endpoint URL."
+ fi
+
+ load_user_data
+ parse_jon_server_url
+
+ if [ -z $jon_server_url ]; then
+ echo "Warning: Failed find jon.server.url parameter. You need to " \
+ "manually set the rhq.agent.server.bind-address property in " \
+ "<RHQ_AGENT>/conf/agent-configuration.xml. Cannot start agent."
+ return 1
+ fi
+
+ export RHQ_AGENT_CMDLINE_OPTS="--daemon $RHQ_AGENT_CMDLINE_OPTS"
+ export RHQ_AGENT_CMDLINE_OPTS="-Drhq.agent.server.bind-address=$jon_server_url $RHQ_AGENT_CMDLINE_OPTS"
+
+ return 0
+}
+
+
+cd $RHQ_AGENT_HOME/bin
+
+case "$1" in
+'init')
+ init "force"
+ ;;
+'start')
+ if init
+ then
+ ./rhq-agent-wrapper.sh start
+ else
+ echo "Failed: Cannot start the agent do to previous initialization errors"
+ fi
+ ;;
+'stop')
+ ./rhq-agent-wrapper.sh stop
+ ;;
+'kill')
+ ./rhq-agent-wrapper.sh kill
+ ;;
+'status')
+ ./rhq-agent-wrapper.sh status
+ ;;
+'restart')
+ ./rhq-agent-wrapper.sh restart
+ ;;
+'quiet-restart')
+ ./rhq-agent-wrapper.sh quiet-restart
+ ;;
+'echo')
+ echo "script: $0"
+ ;;
+*)
+ echo "Usage: $0 { init | start | stop | kill | restart | status }"
+ exit 1
+ ;;
+esac
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagement.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagement.java
index 42dd631..1a51f43 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagement.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagement.java
@@ -87,6 +87,10 @@ public class AgentManagement implements AgentManagementMBean, MBeanRegistration
m_agent = agent;
}
+ public void switchToServer(String server) {
+ m_agent.switchToServer(server);
+ }
+
public void restart() {
// restarting the agent is a suicidal act - this MBean instance will
// be unregistered after we shutdown. Therefore, we must do this in a
diff --git a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagementMBean.java b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagementMBean.java
index 62108a1..1be62dc 100644
--- a/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagementMBean.java
+++ b/modules/enterprise/agent/src/main/java/org/rhq/enterprise/agent/AgentManagementMBean.java
@@ -82,6 +82,8 @@ public interface AgentManagementMBean {
*/
String PLUGIN_INFO_MD5 = "md5";
+ void switchToServer(String server);
+
/**
* This will perform an agent <i>hot-restart</i>. The agent will be {@link #shutdown()} and then immediately started
* again. This is usually called after a client has
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
index ae89a83..b5c0ac9 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
@@ -51,6 +51,7 @@ import org.rhq.enterprise.server.alert.engine.internal.AlertConditionCacheCoordi
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.auth.prefs.SubjectPreferencesCache;
import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
+import org.rhq.enterprise.server.cloud.instance.SyncEndpointAddressException;
import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.core.CustomJaasDeploymentServiceMBean;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
@@ -165,6 +166,13 @@ public class StartupServlet extends HttpServlet {
// Establish the current server mode for the server. This will move the server to NORMAL
// mode from DOWN if necessary. This can also affect comm layer behavior.
serverManager.establishCurrentServerMode();
+ if ("true".equals(System.getProperty("rhq.sync.endpoint-address", "false"))) {
+ try {
+ serverManager.syncEndpointAddress();
+ } catch (SyncEndpointAddressException e) {
+ log("Failed to sync server endpoint address.", e);
+ }
+ }
}
/**
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index 1ec4552..b4116aa 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -203,6 +203,8 @@
<property name="rhq.server.enable.ws" value="${rhq.server.enable.ws}" />
<property name="jbossws-native-dist.version" value="${jbossws-native-dist.version}" />
+
+ <property name="rhq.sync.endpoint-address" value="${rhq.sync.endpoint-address}"/>
</ant>
</tasks>
</configuration>
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
index d45932d..c98dd12 100644
--- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
@@ -20,6 +20,8 @@
<property name="default.rhq.server.quartz.selectWithLockSQL" value="SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE" />
<property name="default.rhq.server.quartz.lockHandlerClass" value="org.quartz.impl.jdbcjobstore.StdRowLockSemaphore" />
+ <property name="rhq.sync.endpoint-address" value="false"/>
+
<target name="set-predeploy-prop">
<condition property="predeploy" value="true">
<or>
@@ -604,6 +606,7 @@ rhq.server.plugin-scan-period-ms=${rhq.server.plugin-scan-period-ms}
rhq.autoinstall.enabled=false
rhq.autoinstall.database=auto
rhq.autoinstall.public-endpoint-address=
+rhq.sync.endpoint-address=${rhq.sync.endpoint-address}
</echo>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerBean.java
index cc2c565..be91c65 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerBean.java
@@ -18,6 +18,8 @@
*/
package org.rhq.enterprise.server.cloud.instance;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Collection;
import java.util.List;
@@ -284,6 +286,19 @@ public class ServerManagerBean implements ServerManagerLocal {
Server.OperationMode.MAINTENANCE.name());
}
+ public void syncEndpointAddress() throws SyncEndpointAddressException {
+ Server server = getServer();
+ try {
+ String hostName = InetAddress.getLocalHost().getHostName();
+
+ if (!hostName.equals(server.getAddress())) {
+ server.setAddress(hostName);
+ }
+ } catch (UnknownHostException e) {
+ throw new SyncEndpointAddressException("Failed to sync endpoint address for " + server, e);
+ }
+ }
+
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void beat() {
Server server = getServer();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerLocal.java
index 135db97..04e244c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/ServerManagerLocal.java
@@ -102,6 +102,15 @@ public interface ServerManagerLocal {
void establishCurrentServerMode();
/**
+ * Synchronizes the endpoint address of this server with the host name or address found on the host machine. If the
+ * host name or address of this machine differs from {@link Server#getAddress()} then this server will be updated
+ * with the value of this machine's host name/address.
+ *
+ * @throws SyncEndpointAddressException
+ */
+ void syncEndpointAddress() throws SyncEndpointAddressException;
+
+ /**
* Updates server mtime to register active heart beat
*/
void beat();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/SyncEndpointAddressException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/SyncEndpointAddressException.java
new file mode 100644
index 0000000..a3924d7
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/instance/SyncEndpointAddressException.java
@@ -0,0 +1,20 @@
+package org.rhq.enterprise.server.cloud.instance;
+
+public class SyncEndpointAddressException extends Exception {
+
+ public SyncEndpointAddressException() {
+ super();
+ }
+
+ public SyncEndpointAddressException(String message) {
+ super(message);
+ }
+
+ public SyncEndpointAddressException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SyncEndpointAddressException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 19c8eb8..5c61f8b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -19,13 +19,18 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.io.Serializable;
import java.lang.reflect.Method;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@@ -108,6 +113,9 @@ abstract class AbstractJobWrapper implements Job {
*/
public static final String DATAMAP_IS_CLUSTERED = DATAMAP_LEADER + "isClustered";
+ protected abstract ScheduledJobInvocationContext createContext(ScheduledJobDefinition jobDefinition,
+ ServerPluginContext pluginContext, ServerPluginComponent serverPluginComponent, Map<String, String> jobData);
+
/**
* This is the method that quartz calls when the schedule has triggered. This method will
* delegate to the plugin component that is responsible to do work for the plugin.
@@ -229,7 +237,7 @@ abstract class AbstractJobWrapper implements Job {
ScheduledJobDefinition jobDefinition = new ScheduledJobDefinition(jobId, true, jobClass, jobMethodName,
scheduleType, callbackData);
ServerPluginContext pluginContext = pluginManager.getServerPluginContext(pluginEnv);
- params[0] = new ScheduledJobInvocationContext(jobDefinition, pluginContext, pluginComponent);
+ params[0] = createContext(jobDefinition, pluginContext, pluginComponent,dataMap);
} catch (NoSuchMethodException e) {
try {
// see if there is a no-arg method of the given name
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index b8e760c..c7fc556 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -19,6 +19,7 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
index 13cbfc4..dfbb941 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
@@ -19,6 +19,10 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.util.Map;
+
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+
/**
* The actual quartz job that the plugin container will submit when it needs to invoke
* a concurrent scheduled job on behalf of a plugin. This is a normal non-stateful "job"
@@ -31,4 +35,9 @@ package org.rhq.enterprise.server.plugin.pc;
* @author John Mazzitelli
*/
public class ConcurrentJobWrapper extends AbstractJobWrapper {
+ @Override
+ protected ScheduledJobInvocationContext createContext(ScheduledJobDefinition jobDefinition,
+ ServerPluginContext pluginContext, ServerPluginComponent serverPluginComponent, Map<String, String> jobData) {
+ return new ScheduledJobInvocationContext(jobDefinition, pluginContext, serverPluginComponent);
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
index cdb0ebf..b69fc9c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
@@ -19,12 +19,26 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
/**
+ * <p>
* A scheduled job's invocation method can take a single argument of this type.
* If this is the case, the scheduled job's method will be passed an object of this type enabling
* the job being invoked to be given information about the invocation.
+ * </p>
+ * <p>
+ * When a job is <strong>not</strong> marked for concurrent execution, it can store data in the context in the form of
+ * key/value properties. These properties will be persisted across invocations of the job. If the job is marked to as
+ * clustered, the job data will persist across server restarts as well. Lastly, if the job is marked to run
+ * concurrently, the methods for accessing/updating properties will throw an exception.
+ * </p>
*
* @author John Mazzitelli
*/
@@ -68,4 +82,60 @@ public class ScheduledJobInvocationContext {
public ServerPluginComponent getServerPluginComponent() {
return serverPluginComponent;
}
+
+ /**
+ * Adds a property to the context that is persisted across invocations of the job. The property is persisted across
+ * server restarts <strong>only if</strong> the scheduled job is declared to run as clustered. Note that method
+ * will throw an exception if the job is declared for concurrent execution.
+ *
+ * @param key The property name
+ * @param value The property value
+ * @throws UnsupportedOperationException if the job is marked for concurrent execution
+ */
+ public void put(String key, String value) {
+ throw new UnsupportedOperationException("This operation is only supported for stateful jobs.");
+ }
+
+ /**
+ * Retrieves a property value from the context.
+ *
+ * @param key The property key
+ * @return The property value or <code>null<code> if the key is not found
+ * @throws UnsupportedOperationException if the job is marked for concurrent execution
+ */
+ public String get(String key) {
+ throw new UnsupportedOperationException("This operation is only supported for stateful jobs.");
+ }
+
+ /**
+ * Removes the property value associated with the specified key
+ *
+ * @param key The property key
+ * @return The value previously associated with the key or <code>null</code> if the key is present in the context
+ * @throws UnsupportedOperationException if the job is marked for concurrent execution
+ */
+ public String remove(String key) {
+ throw new UnsupportedOperationException("This operation is only supported for stateful jobs.");
+ }
+
+ /**
+ * Checks to see whether or not the property key is stored in the context.
+ * @param key The property key
+ * @return <code>true</code> if the key is found, <code>false</code> otherwise.
+ * @throws UnsupportedOperationException if the job is marked for concurrent execution
+ */
+ public boolean containsKey(String key) {
+ throw new UnsupportedOperationException("This operation is only supported for stateful jobs.");
+ }
+
+ /**
+ * Returns a <strong>read-only</strong> view of the properties stored in the context.
+ *
+ * @return A <strong>read-only</strong> view of the properties stored in the context.
+ * @throws UnsupportedOperationException if the job is marked for concurrent execution
+ */
+ public Map<String, String> getJobData() {
+ throw new UnsupportedOperationException("This operation is only supported for stateful jobs.");
+ }
+
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
index d04558b..61a151a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
@@ -19,8 +19,12 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.util.Map;
+
import org.quartz.StatefulJob;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+
/**
* The actual quartz job that the plugin container will submit when it needs to invoke
* a scheduled job on behalf of a plugin. This is a "stateful job" which tells quartz
@@ -33,4 +37,9 @@ import org.quartz.StatefulJob;
* @author John Mazzitelli
*/
public class StatefulJobWrapper extends AbstractJobWrapper implements StatefulJob {
+ @Override
+ protected ScheduledJobInvocationContext createContext(ScheduledJobDefinition jobDefinition,
+ ServerPluginContext pluginContext, ServerPluginComponent serverPluginComponent, Map<String, String> jobData) {
+ return new StatefulScheduledJobInvocationContext(jobDefinition, pluginContext, serverPluginComponent, jobData);
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulScheduledJobInvocationContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulScheduledJobInvocationContext.java
new file mode 100644
index 0000000..c526400
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulScheduledJobInvocationContext.java
@@ -0,0 +1,65 @@
+package org.rhq.enterprise.server.plugin.pc;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+
+public class StatefulScheduledJobInvocationContext extends ScheduledJobInvocationContext {
+ private Map<String, String> jobData;
+
+ public StatefulScheduledJobInvocationContext(ScheduledJobDefinition jobDefinition,
+ ServerPluginContext pluginContext, ServerPluginComponent serverPluginComponent, Map<String, String> jobData) {
+ super(jobDefinition, pluginContext, serverPluginComponent);
+ this.jobData = jobData;
+ }
+
+ /**
+ * Adds a property to the context that is persisted across invocations of the job.
+ *
+ * @param key The property name
+ * @param value The property value
+ */
+ public void put(String key, String value) {
+ jobData.put(key, value);
+ }
+
+ /**
+ * Retrieves a property value from the context.
+ *
+ * @param key The property key
+ * @return The property value or <code>null<code> if the key is not found
+ */
+ public String get(String key) {
+ return jobData.get(key);
+ }
+
+ /**
+ * Removes the property value associated with the specified key
+ *
+ * @param key The property key
+ * @return The value previously associated with the key or <code>null</code> if the key is present in the context
+ */
+ public String remove(String key) {
+ return jobData.remove(key);
+ }
+
+ /**
+ * Checks to see whether or not the property key is stored in the context.
+ * @param key The property key
+ * @return <code>true</code> if the key is found, <code>false</code> otherwise.
+ */
+ public boolean containsKey(String key) {
+ return jobData.containsKey(key);
+ }
+
+ /**
+ * Returns a <strong>read-only</strong> view of the properties stored in the context.
+ *
+ * @return A <strong>read-only</strong> view of the properties stored in the context.
+ */
+ public Map<String, String> getJobData() {
+ return Collections.unmodifiableMap(jobData);
+ }
+
+}
diff --git a/modules/enterprise/server/plugins/cloud/pom.xml b/modules/enterprise/server/plugins/cloud/pom.xml
new file mode 100644
index 0000000..8d10fcd
--- /dev/null
+++ b/modules/enterprise/server/plugins/cloud/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server-plugins-parent</artifactId>
+ <version>3.0.1-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-serverplugin-cloud</artifactId>
+
+ <name>RHQ Enterprise Server Cloud Plugin</name>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/server/...</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/server/...</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/enterprise/server/plugins/cloud/</scm.module.path>
+ <cobber4j.version>0.1</cobber4j.version>
+ </properties>
+
+ <dependencies>
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <!--
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.0</version>
+ <executions>
+ <execution>
+ <id>copy-libs</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ </artifactItems>
+ <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ -->
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <!--
+ <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+ <profiles>
+
+ <profile>
+ <id>dev</id>
+
+ <properties>
+ <rhq.rootDir>../../../../..</rhq.rootDir>
+ <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
+ <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-serverplugins</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="${rhq.deploymentDir}" />
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating ${deployment.file}...</echo>
+ <jar destfile="${deployment.file}" basedir="${project.build.outputDirectory}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Deleting ${deployment.file}...</echo>
+ <delete file="${deployment.file}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" />
+ <echo>*** Updating META-INF dir in ${deployment.file}...</echo>
+ <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}">
+ <patternset>
+ <include name="META-INF/**" />
+ </patternset>
+ </unjar>
+ <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF" update="true">
+ </jar>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+
+ </profiles>
+</project>
diff --git a/modules/enterprise/server/plugins/cloud/src/main/java/org/rhq/enterprise/server/plugins/cloud/CloudServerPluginComponent.java b/modules/enterprise/server/plugins/cloud/src/main/java/org/rhq/enterprise/server/plugins/cloud/CloudServerPluginComponent.java
new file mode 100644
index 0000000..88eb3ba
--- /dev/null
+++ b/modules/enterprise/server/plugins/cloud/src/main/java/org/rhq/enterprise/server/plugins/cloud/CloudServerPluginComponent.java
@@ -0,0 +1,193 @@
+package org.rhq.enterprise.server.plugins.cloud;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.cloud.Server;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.criteria.ResourceCriteria;
+import org.rhq.core.domain.resource.Agent;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.cloud.CloudManagerLocal;
+import org.rhq.enterprise.server.operation.OperationManagerLocal;
+import org.rhq.enterprise.server.operation.ResourceOperationSchedule;
+import org.rhq.enterprise.server.plugin.pc.ControlFacet;
+import org.rhq.enterprise.server.plugin.pc.ControlResults;
+import org.rhq.enterprise.server.plugin.pc.ScheduledJobInvocationContext;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class CloudServerPluginComponent implements ServerPluginComponent, ControlFacet {
+
+ private static Log log = LogFactory.getLog(CloudServerPluginComponent.class);
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ }
+
+ public void start() {
+ }
+
+ public void stop() {
+ }
+
+ public void shutdown() {
+ }
+
+ public ControlResults invoke(String name, Configuration parameters) {
+ if ("syncServerEndpoint".equals(name)) {
+ String serverName = parameters.getSimpleValue("name", null);
+ String serverAddr = parameters.getSimpleValue("address", null);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Invoked syncServerEndpoint with [name: " + serverName + ", address: " + serverAddr + "]");
+ }
+
+ ControlResults results = new ControlResults();
+
+ CloudManagerLocal cloudMgr = LookupUtil.getCloudManager();
+ Server server = cloudMgr.getServerByName(serverName);
+
+ if (server == null) {
+ log.warn("Failed to locate server. No address sync will be performed.");
+ results.setError("No update performed. Failed to find server " + server.getName());
+ return results;
+ }
+
+ if (serverAddr != null) {
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+
+ server.setAddress(serverAddr);
+ cloudMgr.updateServer(subjectMgr.getOverlord(), server);
+ }
+
+ int updateCount = notifyAgents(server);
+
+ Configuration complexResults = results.getComplexResults();
+ complexResults.put(new PropertySimple("results", updateCount + " agents have been updated."));
+
+ if (log.isDebugEnabled()) {
+ log.debug("Notified " + updateCount + " agents of the address change.");
+ }
+
+ return results;
+ }
+
+ return null;
+ }
+
+ public void syncServerEndpoints(ScheduledJobInvocationContext context) {
+ log.debug("Preparing to sync server endpoints.");
+
+ CloudManagerLocal cloudMgr = LookupUtil.getCloudManager();
+ List<Server> servers = cloudMgr.getAllServers();
+
+ purgeStaleServers(context, servers);
+
+ for (Server server : servers) {
+ if (!context.containsKey("server:" + server.getName())) {
+ log.debug("Adding server [" + server.getName() + "] to sync list.");
+ context.put("server:" + server.getName(), server.getAddress());
+ } else if (addressChanged(context, server)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Detected address change for " + server);
+ log.debug("Old address was " + context.get("server:" + server.getName() + ", new address is " +
+ server.getAddress()));
+ }
+ context.put("server:" + server.getName(), server.getAddress());
+ notifyAgents(server);
+ }
+ }
+ }
+
+ private void purgeStaleServers(ScheduledJobInvocationContext context, List<Server> servers) {
+ List<String> purgeList = new ArrayList<String>();
+
+ Set<String> serverNames = new HashSet<String>();
+ for (Server server : servers) {
+ serverNames.add(server.getName());
+ }
+
+ for (String key : context.getJobData().keySet()) {
+ if (key.startsWith("server:")) {
+ String serverName = parseServerName(key);
+ if (!serverNames.contains(serverName)) {
+ log.debug("Detected a stale server: " + serverName);
+ log.debug(serverName + " will be removed from the sync list.");
+ purgeList.add(key);
+ }
+ }
+ }
+
+ for (String staleServer : purgeList) {
+ context.remove(staleServer);
+ }
+ }
+
+ private String parseServerName(String key) {
+ return key.substring("server:".length());
+ }
+
+ private boolean addressChanged(ScheduledJobInvocationContext context, Server server) {
+ String lastKnownAddr = context.get("server:" + server.getName());
+ return !server.getAddress().endsWith(lastKnownAddr);
+ }
+
+ @SuppressWarnings("unchecked")
+ private int notifyAgents(Server server) {
+ EntityManager entityMgr = LookupUtil.getEntityManager();
+ String queryString = "select r " +
+ "from Resource r " +
+ "where r.resourceType.plugin = :pluginName and " +
+ "r.resourceType.name = :resourceTypeName and " +
+ "r.agent in (select a " +
+ "from Agent a " +
+ "where a.server = :server)";
+
+ List<Resource> agents = entityMgr.createQuery(queryString)
+ .setParameter("pluginName", "RHQAgent")
+ .setParameter("resourceTypeName", "RHQ Agent")
+ .setParameter("server", server)
+ .getResultList();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Found " + agents.size() + " to be updated with new server endpoint for " + server);
+ }
+
+ int numUpdated = 0;
+ for (Resource agent : agents) {
+ updateAgent(agent, server);
+ numUpdated++;
+ }
+
+ return numUpdated;
+ }
+
+ private void updateAgent(Resource agent, Server server) {
+ OperationManagerLocal operationMgr = LookupUtil.getOperationManager();
+ SubjectManagerLocal subjectMgr = LookupUtil.getSubjectManager();
+
+ Configuration params = new Configuration();
+ params.put(new PropertySimple("server", server.getAddress()));
+
+ ResourceOperationSchedule schedule = operationMgr.scheduleResourceOperation(subjectMgr.getOverlord(),
+ agent.getId(), "switchToServer", 0, 0, 0, 0, params, "Cloud Plugin: syncing server endpoint address");
+
+ if (log.isDebugEnabled()) {
+ log.debug("Schedule address sync for agent [name: " + agent.getName() + "].");
+ log.debug("Operation schedule is " + schedule);
+ }
+ }
+}
diff --git a/modules/enterprise/server/plugins/cloud/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/cloud/src/main/resources/META-INF/rhq-serverplugin.xml
new file mode 100644
index 0000000..e6944c0
--- /dev/null
+++ b/modules/enterprise/server/plugins/cloud/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -0,0 +1,57 @@
+<generic-plugin name="CloudServerPlugin"
+ displayName="Cloud"
+ description=""
+ package="org.rhq.enterprise.server.plugins.cloud"
+ disabledOnDiscovery="false"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+ <serverplugin:plugin-component class="CloudServerPluginComponent">
+ <serverplugin:control name="syncServerEndpoint" description="">
+ <serverplugin:parameters>
+ <c:simple-property name="name"
+ required="true"
+ description="The server name"/>
+ <c:simple-property name="address"
+ required="false"
+ description="If an address is specified, it will overwrite the server's current value
+ in the database. If an address is not specified then the server's
+ current address will be sent down to its agents."/>
+ </serverplugin:parameters>
+ <serverplugin:results>
+ <c:simple-property name="results" description="Contains a status or error message"/>
+ </serverplugin:results>
+ </serverplugin:control>
+ </serverplugin:plugin-component>
+
+ <serverplugin:scheduled-jobs>
+ <c:map-property name="syncServerEndpoints">
+ <c:simple-property name="scheduleType"
+ type="string"
+ required="true"
+ default="periodic"
+ summary="true"
+ description="Indicates the type of trigger this synchronize job will use">
+ <c:property-options>
+ <c:option value="periodic" default="true"/>
+ <c:option value="cron"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="scheduleTrigger" default="300000"/>
+ <c:simple-property name="concurrent"
+ type="boolean"
+ required="true"
+ default="false"
+ summary="false"
+ readOnly="true"
+ description="This must always be false - only want one sync job running at a time"/>
+ <c:simple-property name="clustered"
+ type="boolean"
+ required="true"
+ default="true"
+ summary="false"
+ readOnly="true"
+ description="This must always be true"/>
+ </c:map-property>
+ </serverplugin:scheduled-jobs>
+</generic-plugin>
\ No newline at end of file
diff --git a/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentServerComponent.java b/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentServerComponent.java
index 2c83140..d352ae9 100644
--- a/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentServerComponent.java
+++ b/modules/plugins/rhq-agent/src/main/java/org/rhq/plugins/agent/AgentServerComponent.java
@@ -194,6 +194,9 @@ public class AgentServerComponent extends JMXServerComponent implements JMXCompo
throw eie;
}
}
+ } else if (name.equals("switchToServer")) {
+ String server = params.getSimpleValue("server", null);
+ getAgentBean().getOperation(name).invoke(server);
} else {
// this should really never happen
throw new IllegalArgumentException("Operation [" + name + "] does not support params");
diff --git a/modules/plugins/rhq-agent/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-agent/src/main/resources/META-INF/rhq-plugin.xml
index 2361c2d..438cbd5 100644
--- a/modules/plugins/rhq-agent/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-agent/src/main/resources/META-INF/rhq-plugin.xml
@@ -170,6 +170,17 @@
</results>
</operation>
+ <operation name="switchToServer"
+ description="Tell the agent to immediately switch to another server. The given server can be a simple
+ hostname in which case, the current transport, port and transport parameters being used to
+ talk to the current server will stay the same. Otherwise, it will be assumed the server
+ is a full endpoint URL.">
+ <parameters>
+ <c:simple-property name="server" description="A simple hostname or a full endpoint URL"
+ required="true"/>
+ </parameters>
+ </operation>
+
<metric property="Trait.SigarVersion"
displayName="SIGAR Version"
dataType="trait"
diff --git a/pom.xml b/pom.xml
index ba31907..3c49e2d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -147,6 +147,18 @@
<rhq.server.enable.ws>false</rhq.server.enable.ws>
+ <!--
+ When this property is set to true will compare its endpoint address
+ that is stored in the database against the actual host name/IP address
+ returned by the host system. If they differ, the address stored in the
+ datbase will be updated to the value found on the host machine. While
+ host name changes are/should be uncommon in a typical deployment, they
+ are more common in a cloud deployment such as EC2. And in a cloud
+ deployment like EC2, we want to turn this behavior on to ensure that
+ the server endpoint accurately reflects the current machine address.
+ -->
+ <rhq.sync.endpoint-address>false</rhq.sync.endpoint-address>
+
<!-- NOTE: The below line is a workaround for a Maven bug, where it does not expand settings.* properties
used in the distributionManagement section of the POM. -->
<localRepository>${user.home}/.m2/repository</localRepository>
13 years, 3 months
[rhq] modules/enterprise
by mazz
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java | 13 ++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDetailsView.java | 22 +++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeHistoryView.java | 63 +++++++++-
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 8 +
4 files changed, 99 insertions(+), 7 deletions(-)
New commits:
commit 0846d3579e9e5c16617493a370ba6db998572b49
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Mar 14 15:23:27 2011 -0400
fix the events history ui - provide i18n with icons - show hover for full name of source, pretty up details view
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
index 1894c09..8b7cb0b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/ImageManager.java
@@ -405,6 +405,19 @@ public class ImageManager {
return "subsystems/event/Events" + icon + "_16.png";
}
+ /**
+ * This returns an icon of the badge (e.g. the red X or the blue I) without the
+ * event icon. This is used if you have a table of events and the user knows they are
+ * events so there is no need to show the event icon itself- showing a bigger badge
+ * to indicate severity is more useful.
+ *
+ * @param severity
+ * @return badge icon
+ */
+ public static String getEventSeverityBadge(EventSeverity severity) {
+ return "subsystems/event/" + severity.name() + "_16.png";
+ }
+
public static String getEventLargeIcon() {
return "subsystems/event/Events_24.png";
}
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDetailsView.java
index ea01164..40a342f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDetailsView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeDetailsView.java
@@ -34,6 +34,7 @@ import org.rhq.core.domain.event.composite.EventComposite;
import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.gui.coregui.client.BookmarkableView;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.ViewPath;
import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup;
import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableDynamicForm;
@@ -83,12 +84,31 @@ public class EventCompositeDetailsView extends LocatableVLayout implements Bookm
DynamicForm form = new LocatableDynamicForm(extendLocatorId("form"));
form.setWidth100();
form.setHeight100();
+ form.setWrapItemTitles(false);
StaticTextItem id = new StaticTextItem("id", MSG.common_title_id());
id.setValue(composite.getEventId());
StaticTextItem severity = new StaticTextItem("severity", MSG.view_inventory_eventHistory_severity());
- severity.setValue(composite.getSeverity().name());
+ String severityValue = Canvas.imgHTML(ImageManager.getEventSeverityBadge(composite.getSeverity()));
+ switch (composite.getSeverity()) {
+ case DEBUG:
+ severityValue += MSG.common_severity_debug();
+ break;
+ case INFO:
+ severityValue += MSG.common_severity_info();
+ break;
+ case WARN:
+ severityValue += MSG.common_severity_warn();
+ break;
+ case ERROR:
+ severityValue += MSG.common_severity_error();
+ break;
+ case FATAL:
+ severityValue += MSG.common_severity_fatal();
+ break;
+ }
+ severity.setValue(severityValue);
StaticTextItem source = new StaticTextItem("source", MSG.view_inventory_eventHistory_sourceLocation());
source.setValue(composite.getSourceLocation());
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeHistoryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeHistoryView.java
index 7209c17..0657f04 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeHistoryView.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/event/EventCompositeHistoryView.java
@@ -27,10 +27,12 @@ import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.SortSpecifier;
+import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.SortDirection;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.grid.CellFormatter;
+import com.smartgwt.client.widgets.grid.HoverCustomizer;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
@@ -39,6 +41,7 @@ import org.rhq.core.domain.event.EventSeverity;
import org.rhq.core.domain.resource.composite.ResourceComposite;
import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite;
import org.rhq.enterprise.gui.coregui.client.CoreGUI;
+import org.rhq.enterprise.gui.coregui.client.ImageManager;
import org.rhq.enterprise.gui.coregui.client.components.form.EnumSelectItem;
import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction;
import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement;
@@ -50,7 +53,7 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
/**
* @author Joseph Marques
*/
-public class EventCompositeHistoryView extends TableSection {
+public class EventCompositeHistoryView extends TableSection<EventCompositeDatasource> {
private static SortSpecifier DEFAULT_SORT_SPECIFIER = new SortSpecifier("timestamp", SortDirection.DESCENDING);
private EntityContext context;
@@ -97,18 +100,53 @@ public class EventCompositeHistoryView extends TableSection {
@Override
protected void configureTable() {
- ListGridField timestampField = new ListGridField("timestamp", MSG.view_inventory_eventHistory_timestamp(), 125);
- ListGridField severityField = new ListGridField("severity", MSG.view_inventory_eventHistory_severity(), 75);
+ ListGridField timestampField = new ListGridField("timestamp", MSG.view_inventory_eventHistory_timestamp());
+
+ ListGridField severityField = new ListGridField("severity", MSG.view_inventory_eventHistory_severity());
+ severityField.setAlign(Alignment.CENTER);
severityField.setCellFormatter(new CellFormatter() {
public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
- return Canvas.imgHTML("subsystems/event/" + o + "_16.png", 16, 16) + o;
+ String icon = ImageManager.getEventSeverityBadge(EventSeverity.valueOf(o.toString()));
+ return Canvas.imgHTML(icon);
+ }
+ });
+ severityField.setShowHover(true);
+ severityField.setHoverCustomizer(new HoverCustomizer() {
+ @Override
+ public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) {
+ EventSeverity severity = EventSeverity.valueOf(record.getAttribute("severity"));
+ switch (severity) {
+ case DEBUG:
+ return MSG.common_severity_debug();
+ case INFO:
+ return MSG.common_severity_info();
+ case WARN:
+ return MSG.common_severity_warn();
+ case ERROR:
+ return MSG.common_severity_error();
+ case FATAL:
+ return MSG.common_severity_fatal();
+ }
+ return null;
}
});
+
ListGridField detailsField = new ListGridField("details-highlight", MSG.view_inventory_eventHistory_details());
- ListGridField sourceField = new ListGridField("source", MSG.view_inventory_eventHistory_sourceLocation(), 275);
+ detailsField.setCellFormatter(new CellFormatter() {
+ @Override
+ public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
+ if (((String) value).length() <= 200) {
+ return (String) value;
+ } else {
+ return ((String) value).substring(0, 200); // first 200 chars
+ }
+ }
+ });
+
+ ListGridField sourceField = new ListGridField("source", MSG.view_inventory_eventHistory_sourceLocation());
sourceField.setCellFormatter(new CellFormatter() {
public String format(Object o, ListGridRecord listGridRecord, int i, int i1) {
- String sourceLocation = (String) o;
+ String sourceLocation = listGridRecord.getAttribute("source");
int length = sourceLocation.length();
if (length > 40) {
return "..." + sourceLocation.substring(length - 40); // the last 40 chars
@@ -116,6 +154,19 @@ public class EventCompositeHistoryView extends TableSection {
return sourceLocation;
}
});
+ sourceField.setShowHover(true);
+ sourceField.setHoverCustomizer(new HoverCustomizer() {
+ @Override
+ public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) {
+ String sourceLocation = record.getAttribute("source");
+ return (sourceLocation.length() > 40) ? sourceLocation : null;
+ }
+ });
+
+ timestampField.setWidth("20%");
+ severityField.setWidth("25");
+ detailsField.setWidth("*");
+ sourceField.setWidth("20%");
setListGridFields(timestampField, severityField, detailsField, sourceField);
diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
index 8293144..a6b9716 100644
--- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
+++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties
@@ -81,6 +81,14 @@ common_unit_weeks = weeks
common_unit_months = months
common_unit_years = years
+# Common Severities
+#------------------
+common_severity_debug = Debug
+common_severity_info = Info
+common_severity_warn = Warn
+common_severity_error = Error
+common_severity_fatal = Fatal
+
# Common Titles
#--------------
common_title_address = Address
13 years, 3 months