.classpath | 6 modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 2 modules/core/domain/src/main/java/org/rhq/core/domain/auth/Subject.java | 12 modules/core/domain/src/main/java/org/rhq/core/domain/authz/Role.java | 25 modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleGroup.java | 6 modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleNotFoundException.java | 49 + modules/core/domain/src/main/java/org/rhq/core/domain/bundle/composite/BundleGroupAssignmentComposite.java | 95 ++ modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java | 30 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java | 3 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesDataSource.java | 1 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java | 92 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java | 6 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java | 86 +- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java | 45 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleCreateWizard.java | 51 + modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java | 285 +++++++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleSummaryStep.java | 14 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java | 106 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationDataSource.java | 2 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java | 6 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupEditView.java | 182 ++++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupSelector.java | 22 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java | 97 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java | 187 ++++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java | 12 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java | 104 +- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java | 212 ++++- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java | 36 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionListView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/AuthorizedTableAction.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/BundleAuthorizedTableAction.java | 125 +++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/RoleAuthorizedTableAction.java | 85 ++ modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java | 11 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java | 38 - modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/FavoriteGroupsPortlet.java | 2 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AuthorizationGWTService.java | 13 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java | 20 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/InventoryView.java | 14 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/history/AbstractOperationHistoryListView.java | 2 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupListView.java | 10 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/MembersView.java | 2 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java | 10 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java | 26 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AuthorizationGWTServiceImpl.java | 37 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java | 7 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java | 101 ++ modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 8 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties | 8 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties | 10 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties | 8 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties | 8 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties | 8 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties | 9 modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties | 8 modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java | 95 +- modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java | 2 modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java | 2 modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml | 18 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerBean.java | 15 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerLocal.java | 13 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java | 23 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerRemote.java | 6 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java | 377 +++++++--- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java | 78 +- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java | 75 + 70 files changed, 2602 insertions(+), 474 deletions(-)
New commits: commit 47c209a0a942f6c9ec2bc68c192c7dc245c2cafc Merge: 7807543 e7f325a Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 20 16:25:45 2013 -0400
Merge branch 'feature/bundle-gui'
Conflicts: .classpath modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml
diff --cc modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 5bfa334,b5a4357..5840a08 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@@ -74,7 -81,7 +81,7 @@@ <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> -- <method>void assignBundlesToBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method> ++ <method>void assignBundlesToBundleGroup(org.rhq.core.domain.auth.Subject, int[], int[])</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
@@@ -137,7 -144,7 +144,14 @@@ <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> -- <method>void unassignBundlesFromBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method> ++ <method>void unassignBundlesFromBundleGroup(org.rhq.core.domain.auth.Subject, int[], int[])</method> ++ <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> ++ </difference> ++ ++ <difference> ++ <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> ++ <differenceType>7012</differenceType> <!-- method added to an interface --> ++ <method>org.rhq.core.domain.bundle.BundleGroup updateBundleGroup(org.rhq.core.domain.auth.Subject subject, org.rhq.core.domain.bundle.BundleGroup bundleGroup)</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
commit e7f325aefa9da750a7e69ec01513b573a46481f1 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 20 16:05:20 2013 -0400
fix merge issue
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 2c48bbd..6adccba 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -1943,7 +1943,7 @@ </schemaSpec>
<schemaSpec version="2.125"> - <!-- Note, JON 3.1.2 includes this already but it is safe to re-execute --> + <!-- Note, JON 3.1.2 includes this already but it is safe to re-execute --> <!-- We were using a buggy version of password obfuscation from JBoss AS. This task sets the affected passwords to NULL. Fortunately, this currently affects only CSP content sources, so the damage is not huge from the user perspective. --> @@ -2211,26 +2211,6 @@ </schema-directSQL> </schemaSpec>
- <schemaSpec version="2.137"> - <schema-addColumn table="RHQ_STORAGE_NODE" column="MAINTENANCE_PENDING" columnType="BOOLEAN"/> - <schema-addColumn table="RHQ_STORAGE_NODE" column="ERROR_MSG" columnType="LONGVARCHAR"/> - <schema-addColumn table="RHQ_STORAGE_NODE" column="RESOURCE_OP_HIST_ID" columnType="INTEGER"/> - <schema-directSQL> - <statement desc="Creating RHQ_STORAGE_NODE foreign key to RHQ_OPERATION_HISTORY"> - ALTER TABLE RHQ_STORAGE_NODE - ADD CONSTRAINT RHQ_SN_OP_HIST_ID_FK - FOREIGN KEY (RESOURCE_OP_HIST_ID) - REFERENCES RHQ_OPERATION_HISTORY (ID) - </statement> - <statement targetDBVendor="postgresql" desc="Set maintenance_pending flag to false for existing storage nodes"> - UPDATE RHQ_STORAGE_NODE SET IGNORED = false - </statement> - <statement targetDBVendor="oracle" desc="Set maintenance_pending flag to false for existing storage nodes"> - UPDATE RHQ_STORAGE_NODE SET IGNORED = 0 - </statement> - </schema-directSQL> - </schemaSpec> - </dbupgrade> </target> </project>
commit f8127fd04d6e168794d1b6e5f22949b5e5f92b09 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 20 15:41:42 2013 -0400
add jsandas latest library additions
diff --git a/.classpath b/.classpath index 63f9170..6985799 100644 --- a/.classpath +++ b/.classpath @@ -392,5 +392,8 @@ <classpathentry kind="var" path="M2_REPO/commons-configuration/commons-configuration/1.6/commons-configuration-1.6.jar"/> <classpathentry kind="var" path="M2_REPO/org/apache/maven/plugin-tools/maven-plugin-annotations/3.2/maven-plugin-annotations-3.2.jar"/> <classpathentry kind="var" path="M2_REPO/org/jboss/jboss-vfs/3.1.0.Final/jboss-vfs-3.1.0.Final.jar"/> + <classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-math3/3.1.1/commons-math3-3.1.1.jar"/> + <classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-databind/2.1.1/jackson-databind-2.1.1.jar"/> + <classpathentry kind="var" path="M2_REPO/com/fasterxml/jackson/core/jackson-core/2.1.1/jackson-core-2.1.1.jar"/> <classpathentry kind="output" path="eclipse-classes"/> </classpath>
commit fb39c1968e72e7aa65146b2d27142abbe2001ab5 Author: Lukas Krejci lkrejci@redhat.com Date: Tue Aug 20 14:24:39 2013 +0200
[BZ 988881] - Removed missing i18n, cancel avail checking timers on logout.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java index fbbf0a8..8fdaf6e 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java @@ -395,9 +395,14 @@ public class ResourceTitleBar extends EnhancedVLayout { new AsyncCallback<List<ResourceError>>() { public void onFailure(Throwable caught) { pluginErrors.setVisible(false); - CoreGUI.getErrorHandler().handleError( - MSG.dataSource_resourceErrors_error_fetchFailure(String.valueOf(resourceComposite.getResource() - .getId())), caught); + + if (UserSessionManager.isLoggedOut()) { + resourceAvailAndErrorsRefreshTime.cancel(); + } else { + CoreGUI.getErrorHandler().handleError( + MSG.dataSource_resourceErrors_error_fetchFailure(String.valueOf(resourceComposite.getResource() + .getId())), caught); + }
if (latch != null) { latch.countDown(); @@ -427,9 +432,13 @@ public class ResourceTitleBar extends EnhancedVLayout { @Override public void onFailure(Throwable caught) { availabilityImage.setSrc(ImageManager.getAvailabilityLargeIconFromAvailType(currentAvail)); - CoreGUI.getErrorHandler().handleError("I18N: Failed to refresh the availability", caught); - //MSG.dataSource_resourceErrors_error_fetchFailure(String.valueOf(resourceComposite.getResource() - // .getId())), caught); + + if (UserSessionManager.isLoggedOut()) { + resourceAvailAndErrorsRefreshTime.cancel(); + } else { + CoreGUI.getErrorHandler().handleError(MSG.view_inventory_resource_loadFailed(String.valueOf(resource.getId())), caught); + } + if (latch != null) { latch.countDown(); } else {
commit 89f76f4574f4d592db77d2b23e2af2c48a3908c8 Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 22:25:49 2013 -0400
update logic of updateSchemaIfNecessary to handle removal of nodes
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index 99bd592..b511fe0 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -165,9 +165,8 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa storageNode = storageNodeOperationsHandler.setMode(storageNode, StorageNode.OperationMode.DECOMMISSION); List<StorageNode> storageNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); - storageNodes.add(storageNode);
- boolean runRepair = updateSchemaIfNecessary(storageNodes); + boolean runRepair = updateSchemaIfNecessary(storageNodes.size() + 1, storageNodes.size()); // This is a bit of a hack since the maintenancePending flag is really intended to // queue up storage nodes during cluster maintenance operations. storageNode.setMaintenancePending(runRepair); @@ -205,7 +204,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
@Override public void performAddNodeMaintenance(Subject subject, StorageNode storageNode) { - storageNode.setOperationMode(StorageNode.OperationMode.ADD_MAINTENANCE); List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) .getResultList(); @@ -214,7 +212,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } storageNode.setMaintenancePending(true); clusterNodes.add(storageNode); - boolean runRepair = updateSchemaIfNecessary(clusterNodes); + boolean runRepair = updateSchemaIfNecessary(clusterNodes.size(), clusterNodes.size() + 1); performAddNodeMaintenance(subject, storageNode, runRepair, createPropertyListOfAddresses(SEEDS_LIST, clusterNodes)); } @@ -701,59 +699,92 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa resourceType.getPlugin().equals(STORAGE_NODE_PLUGIN_NAME); }
- private boolean updateSchemaIfNecessary(List<StorageNode> storageNodes) { - // The previous cluster size will be the current size - 1 since we currently only - // support deploying one node at a time. - int previousClusterSize = storageNodes.size() - 1; + private boolean updateSchemaIfNecessary(int previousClusterSize, int newClusterSize) { boolean isRepairNeeded; int replicationFactor = 1;
- if (previousClusterSize >= 4) { - // At 4 nodes we increase the RF to 3. We are not increasing the RF beyond - // that for additional nodes; so, there is no need to run repair if we are - // expanding from a 4 node cluster since the RF remains the same. + if (previousClusterSize == 0) { + throw new IllegalStateException("previousClusterSize cannot be 0"); + } + if (newClusterSize == 0) { + throw new IllegalStateException("newClusterSize cannot be 0"); + } + if (Math.abs(newClusterSize - previousClusterSize) != 1) { + throw new IllegalStateException("The absolute difference between previousClusterSize[" + + previousClusterSize + "] and newClusterSize[" + newClusterSize + "] must be 1"); + } + + if (newClusterSize == 1) { + isRepairNeeded = false; + replicationFactor = 1; + } else if (previousClusterSize > 4 && newClusterSize == 4) { isRepairNeeded = false; - } else if (previousClusterSize == 1) { - // The RF will increase since we are going from a single to a multi-node - // cluster; therefore, we want to run repair. + } else if (previousClusterSize == 4 && newClusterSize == 3) { isRepairNeeded = true; replicationFactor = 2; - } else if (previousClusterSize == 2) { - if (storageNodes.size() > 3) { - // If we go from 2 to > 3 nodes we will increase the RF to 3; therefore - // we want to run repair. - isRepairNeeded = true; - replicationFactor = 3; - } else { - // If we go from 2 to 3 nodes, we keep the RF at 2 so there is no need - // to run repair. - isRepairNeeded = false; - } - } else if (previousClusterSize == 3) { - // We are increasing the cluster size > 3 which means the RF will be - // updated to 3; therefore, we want to run repair. + } else if (previousClusterSize == 3 && newClusterSize == 2) { + isRepairNeeded = false; + } else if (previousClusterSize == 1 && newClusterSize == 2) { + isRepairNeeded = true; + replicationFactor = 2; + } else if (previousClusterSize == 2 && newClusterSize == 3) { + isRepairNeeded = false; + } else if (previousClusterSize == 3 && newClusterSize == 4) { isRepairNeeded = true; replicationFactor = 3; + } else if (previousClusterSize == 4 && newClusterSize > 4) { + isRepairNeeded = false; } else { - // If we cluster size of zero, then something is really screwed up. It - // should always be > 0. - throw new RuntimeException("The previous cluster size should never be zero at this point"); + throw new IllegalStateException("previousClusterSize[" + previousClusterSize + "] and newClusterSize[" + + newClusterSize + "] is not supported"); }
- if (isRepairNeeded) { -// String username = getRequiredStorageProperty(USERNAME_PROPERTY); -// String password = getRequiredStorageProperty(PASSWORD_PROPERTY); -// SchemaManager schemaManager = new SchemaManager(username, password, storageNodes); -// try{ -// schemaManager.updateTopology(); -// } catch (Exception e) { -// log.error("An error occurred while applying schema topology changes", e); + + + +// if (newClusterSize == 1) { +// isRepairNeeded = false; +// replicationFactor = 1; +// } else if (previousClusterSize >= 4) { +// // At 4 nodes we increase the RF to 3. We are not increasing the RF beyond +// // that for additional nodes; so, there is no need to run repair if we are +// // expanding from a 4 node cluster since the RF remains the same. +// isRepairNeeded = false; +// } else if (previousClusterSize == 1) { +// // The RF will increase since we are going from a single to a multi-node +// // cluster; therefore, we want to run repair. +// isRepairNeeded = true; +// replicationFactor = 2; +// } else if (previousClusterSize == 2) { +// if (storageNodes.size() > 3) { +// // If we go from 2 to > 3 nodes we will increase the RF to 3; therefore +// // we want to run repair. +// isRepairNeeded = true; +// replicationFactor = 3; +// } else { +// // If we go from 2 to 3 nodes, we keep the RF at 2 so there is no need +// // to run repair. +// isRepairNeeded = false; // } +// } else if (previousClusterSize == 3) { +// // We are increasing the cluster size > 3 which means the RF will be +// // updated to 3; therefore, we want to run repair. +// isRepairNeeded = true; +// replicationFactor = 3; +// } else { +// // If we cluster size of zero, then something is really screwed up. It +// // should always be > 0. +// throw new RuntimeException("The previous cluster size should never be zero at this point"); +// }
+ if (isRepairNeeded) { updateReplicationFactor(replicationFactor); if (previousClusterSize == 1) { updateGCGraceSeconds(691200); // 8 days } + } else if (newClusterSize == 1) { + updateReplicationFactor(1); + updateGCGraceSeconds(0); }
return isRepairNeeded;
commit a41c58828525cef776fe097e8836652c903f8337 Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 21:21:22 2013 -0400
make sure the mode is updated at the end of each (un)deployment phase
The transaction demarcation has been updated to ensure that upon successful completion of a (un)deployment phase, the storage node's mode will be updated before starting the next phase. Previously it was done in the same transaction, and if starting the next phase failed, then the node's mode would still be set to the previously completed phase. This did not break anything, but it did result in extra work.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 4d4fd17..28723d7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -238,6 +238,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
switch (storageNode.getOperationMode()) { case INSTALLED: + storageNode.setOperationMode(OperationMode.ANNOUNCE); case ANNOUNCE: reset(); storageNodeOperationsHandler.announceStorageNode(subject, storageNode); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index b068734..99bd592 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -82,7 +82,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Announcing " + storageNode + " to storage node cluster."); } - storageNode.setOperationMode(StorageNode.OperationMode.ANNOUNCE); List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); List<StorageNode> allNodes = new ArrayList<StorageNode>(clusterNodes); @@ -113,7 +112,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa public void unannounceStorageNode(Subject subject, StorageNode storageNode) { log.info("Unannouncing " + storageNode);
- storageNode.setOperationMode(StorageNode.OperationMode.UNANNOUNCE); List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); for (StorageNode clusterNode : clusterNodes) { @@ -133,8 +131,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa public void uninstall(Subject subject, StorageNode storageNode) { log.info("Uninstalling " + storageNode);
- storageNode.setOperationMode(StorageNode.OperationMode.UNINSTALL); - if (storageNode.getResource() == null) { finishUninstall(subject, storageNode); } else { @@ -142,6 +138,19 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } }
+ private void finishUninstall(Subject subject, StorageNode storageNode) { + if (storageNode.getResource() != null) { + log.info("Removing storage node resource " + storageNode.getResource() + " from inventory"); + Resource resource = storageNode.getResource(); + storageNodeOperationsHandler.detachFromResource(storageNode); + resourceManager.uninventoryResource(subject, resource.getId()); + } + log.info("Removing storage node entity " + storageNode + " from database"); + entityManager.remove(storageNode); + + log.info(storageNode + " has been undeployed"); + } + @Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void detachFromResource(StorageNode storageNode) { @@ -153,7 +162,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa public void decommissionStorageNode(Subject subject, StorageNode storageNode) { log.info("Preparing to decommission " + storageNode);
- storageNode.setOperationMode(StorageNode.OperationMode.DECOMMISSION); + storageNode = storageNodeOperationsHandler.setMode(storageNode, StorageNode.OperationMode.DECOMMISSION); List<StorageNode> storageNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); storageNodes.add(storageNode); @@ -184,6 +193,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa StorageNode.class).setParameter("address", storageNodeAddress.getHostAddress()).getSingleResult();
if (storageNode.getOperationMode() == StorageNode.OperationMode.BOOTSTRAP) { + // TODO need to add support for HA deployments + // If multiple RHQ servers are running, they will all receive the event + // notification that the node is up and will all wind up calling this method. + storageNode = storageNodeOperationsHandler.setMode(storageNode, StorageNode.OperationMode.ADD_MAINTENANCE); performAddNodeMaintenance(subjectManager.getOverlord(), storageNode); } else { log.info(storageNode + " has already been bootstrapped. Skipping add node maintenance."); @@ -225,7 +238,11 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa StorageNode.class).setParameter("address", storageNodeAddress.getHostAddress()).getSingleResult();
if (storageNode.getOperationMode() == StorageNode.OperationMode.DECOMMISSION) { - storageNode.setOperationMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); + // TODO need to add support for HA deployments + // If multiple RHQ servers are running, they will all receive the event + // notification that the node is up and will all wind up calling this method. + storageNode = storageNodeOperationsHandler.setMode(storageNode, + StorageNode.OperationMode.REMOVE_MAINTENANCE); performRemoveNodeMaintenance(subjectManager.getOverlord(), storageNode); } else { log.info("Remove node maintenance has already been run for " + storageNode); @@ -241,7 +258,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa node.setMaintenancePending(true); } boolean runRepair = storageNode.isMaintenancePending(); - performRemoveNodeMaintenance(subjectManager.getOverlord(), clusterNodes.get(0), runRepair, + performRemoveNodeMaintenance(subject, clusterNodes.get(0), runRepair, createPropertyListOfAddresses(SEEDS_LIST, clusterNodes)); }
@@ -357,8 +374,9 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
if (nextNode == null) { log.info("Successfully announced new storage node to storage cluster"); - newStorageNode.setOperationMode(StorageNode.OperationMode.BOOTSTRAP); - prepareNodeForBootstrap(subject, newStorageNode, addresses.deepCopy(false)); + newStorageNode = storageNodeOperationsHandler.setMode(newStorageNode, + StorageNode.OperationMode.BOOTSTRAP); + storageNodeOperationsHandler.bootstrapStorageNode(subject, newStorageNode); } else { announceStorageNode(subject, newStorageNode, nextNode, addresses.deepCopy(false)); } @@ -369,32 +387,31 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void handleUnannounce(ResourceOperationHistory operationHistory) { StorageNode storageNode = findStorageNode(operationHistory.getResource()); - StorageNode removedStorageNode = null; + StorageNode removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); switch (operationHistory.getStatus()) { case INPROGRESS: // nothing to do here break; case CANCELED: - removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); undeploymentOperationCanceled(storageNode, operationHistory, removedStorageNode); break; case FAILURE: - removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); deploymentOperationFailed(storageNode, operationHistory, removedStorageNode); break; default: // SUCCESS storageNode.setMaintenancePending(false);
- removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); StorageNode nextNode = takeFromMaintenanceQueue(); Subject subject = getSubject(operationHistory); - Configuration params = operationHistory.getParameters(); - PropertyList addresses = params.getList("addresses");
if (nextNode == null) { log.info("Successfully unannounced " + removedStorageNode + " to storage cluster"); + removedStorageNode = storageNodeOperationsHandler.setMode(removedStorageNode, + StorageNode.OperationMode.UNINSTALL); uninstall(getSubject(operationHistory), removedStorageNode); } else { + Configuration params = operationHistory.getParameters(); + PropertyList addresses = params.getList("addresses"); unannounceStorageNode(subject, nextNode, addresses.deepCopy(false)); } } @@ -428,17 +445,15 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void handleAddNodeMaintenance(ResourceOperationHistory resourceOperationHistory) { StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); - StorageNode newStorageNode = null; + StorageNode newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); switch (resourceOperationHistory.getStatus()) { case INPROGRESS: // nothing to do here return; case CANCELED: - newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); deploymentOperationCanceled(storageNode, resourceOperationHistory, newStorageNode); return; case FAILURE: - newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); deploymentOperationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS @@ -448,9 +463,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
if (nextNode == null) { log.info("Finished running add node maintenance on all cluster nodes"); - // TODO replace this with an UPDATE statement - newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); - newStorageNode.setOperationMode(StorageNode.OperationMode.NORMAL); + storageNodeOperationsHandler.setMode(newStorageNode, StorageNode.OperationMode.NORMAL); } else { Configuration parameters = resourceOperationHistory.getParameters(); boolean runRepair = parameters.getSimple(RUN_REPAIR_PROPERTY).getBooleanValue(); @@ -463,19 +476,39 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
@Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void bootstrapStorageNode(Subject subject, StorageNode storageNode) { + List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); + clusterNodes.add(storageNode); + prepareNodeForBootstrap(subject, storageNode, createPropertyListOfAddresses("addresses", clusterNodes)); + } + + private void prepareNodeForBootstrap(Subject subject, StorageNode storageNode, PropertyList addresses) { + if (log.isInfoEnabled()) { + log.info("Preparing to bootstrap " + storageNode + " into cluster..."); + } + StorageClusterSettings clusterSettings = storageClusterSettingsManager.getClusterSettings(subject); + Configuration parameters = new Configuration(); + parameters.put(new PropertySimple("cqlPort", clusterSettings.getCqlPort())); + parameters.put(new PropertySimple("gossipPort", clusterSettings.getGossipPort())); + parameters.put(addresses); + + scheduleOperation(subject, storageNode, parameters, "prepareForBootstrap"); + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void handleRemoveNodeMaintenance(ResourceOperationHistory operationHistory) { StorageNode storageNode = findStorageNode(operationHistory.getResource()); - StorageNode removedStorageNode = null; + StorageNode removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); switch (operationHistory.getStatus()) { case INPROGRESS: // nothing to do here break; case CANCELED: - removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); undeploymentOperationCanceled(storageNode, operationHistory, removedStorageNode); break; case FAILURE: - removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); undeploymentOperationFailed(storageNode, operationHistory, removedStorageNode); break; default: // SUCCESS @@ -485,8 +518,8 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
if (nextNode == null) { log.info("Finished running remove node maintenance on all cluster nodes"); - // TODO replace this with an UPDATE statement - removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); + removedStorageNode = storageNodeOperationsHandler.setMode(removedStorageNode, + StorageNode.OperationMode.UNANNOUNCE); unannounceStorageNode(getSubject(operationHistory), removedStorageNode); } else { Configuration parameters = operationHistory.getParameters(); @@ -537,14 +570,11 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } }
- private void finishUninstall(Subject subject, StorageNode storageNode) { - if (storageNode.getResource() != null) { - log.info("Removing storage node resource " + storageNode.getResource() + " from inventory"); - storageNodeOperationsHandler.detachFromResource(storageNode); - resourceManager.uninventoryResource(subject, storageNode.getResource().getId()); - } - log.info("Removing storage node entity " + storageNode + " from database"); - entityManager.remove(storageNode); + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public StorageNode setMode(StorageNode storageNode, StorageNode.OperationMode newMode) { + storageNode.setOperationMode(newMode); + return entityManager.merge(storageNode); }
private Subject getSubject(ResourceOperationHistory resourceOperationHistory) { @@ -644,27 +674,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return null; }
- @Override - public void bootstrapStorageNode(Subject subject, StorageNode storageNode) { - List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, - StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); - clusterNodes.add(storageNode); - prepareNodeForBootstrap(subject, storageNode, createPropertyListOfAddresses("addresses", clusterNodes)); - } - - private void prepareNodeForBootstrap(Subject subject, StorageNode storageNode, PropertyList addresses) { - if (log.isInfoEnabled()) { - log.info("Preparing to bootstrap " + storageNode + " into cluster..."); - } - StorageClusterSettings clusterSettings = storageClusterSettingsManager.getClusterSettings(subject); - Configuration parameters = new Configuration(); - parameters.put(new PropertySimple("cqlPort", clusterSettings.getCqlPort())); - parameters.put(new PropertySimple("gossipPort", clusterSettings.getGossipPort())); - parameters.put(addresses); - - scheduleOperation(subject, storageNode, parameters, "prepareForBootstrap"); - } - private StorageNode takeFromMaintenanceQueue() { List<StorageNode> storageNodes = entityManager.createQuery("SELECT s FROM StorageNode s WHERE " + "s.operationMode = :operationMode AND s.maintenancePending = :maintenancePending", StorageNode.class) diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java index 5d08dd8..f0a5b98 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java @@ -52,4 +52,6 @@ public interface StorageNodeOperationsHandlerLocal { void performRemoveNodeMaintenance(Subject subject, StorageNode storageNode);
void logError(StorageNode.OperationMode newStorageNodeOperationMode, String error, Exception e); + + StorageNode setMode(StorageNode storageNode, StorageNode.OperationMode newMode); }
commit b85debdf80b0796ff14beff17403b99523478914 Author: Stefan Negrea snegrea@redhat.com Date: Mon Aug 19 15:55:38 2013 -0500
[BZ 998049] Remove all core domain dependencies from Cassandra common modules.
This was causing maven build problems because core domain would need to be built before database util would run and setup the database.
diff --git a/.classpath b/.classpath index 335117b..63f9170 100644 --- a/.classpath +++ b/.classpath @@ -215,6 +215,8 @@ <classpathentry kind="src" path="modules/helpers/ldap-tool/src/main/java"/> <classpathentry kind="src" path="modules/common/cassandra-schema/src/test/java"/> <classpathentry kind="src" path="modules/plugins/rhq-storage/src/test/java"/> + <classpathentry kind="src" path="modules/helpers/metrics-simulator/src/main/java"/> + <classpathentry kind="src" path="modules/common/cassandra-util/src/test/java"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> <classpathentry exported="true" kind="var" path="M2_REPO/org/apache/httpcomponents/httpclient/4.2.3/httpclient-4.2.3.jar" sourcepath="M2_REPO/org/apache/httpcomponents/httpclient/4.2.3/httpclient-4.2.3-sources.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/commons-io/commons-io/2.1/commons-io-2.1.jar" sourcepath="M2_REPO/commons-io/commons-io/2.1/commons-io-2.1-sources.jar"/> diff --git a/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java b/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java index 1aeef43..7c59114 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java +++ b/modules/common/cassandra-ccm/cassandra-ccm-arquillian/src/main/java/org/rhq/cassandra/ccm/arquillian/CCMSuiteDeploymentExtension.java @@ -26,7 +26,6 @@ package org.rhq.cassandra.ccm.arquillian;
import java.io.File; -import java.util.List; import java.util.concurrent.Callable;
import org.jboss.arquillian.config.descriptor.api.ArquillianDescriptor; @@ -62,7 +61,6 @@ import org.rhq.cassandra.ClusterInitService; import org.rhq.cassandra.DeploymentOptions; import org.rhq.cassandra.DeploymentOptionsFactory; import org.rhq.cassandra.schema.SchemaManager; -import org.rhq.core.domain.cloud.StorageNode;
/** * @author John Sanda @@ -114,7 +112,10 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
SchemaManager schemaManager; ClusterInitService clusterInitService = new ClusterInitService(); - List<StorageNode> nodes = null; + + String[] nodes = null; + int[] jmxPorts = null; + int cqlPort = -1;
if (!Boolean.valueOf(System.getProperty("itest.use-external-storage-node", "false"))) {
@@ -131,13 +132,17 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension { options.setStartRpc(true);
ccm = new CassandraClusterManager(options); - nodes = ccm.createCluster(); + ccm.createCluster(); + + nodes = ccm.getNodes(); + jmxPorts = ccm.getJmxPorts(); + cqlPort = ccm.getCqlPort();
ccm.startCluster(false);
try { - clusterInitService.waitForClusterToStart(nodes, nodes.size(), 1500, 20, 5); - schemaManager = new SchemaManager("rhqadmin", "rhqadmin", nodes); + clusterInitService.waitForClusterToStart(nodes, jmxPorts, nodes.length, 20, 5, 1500); + schemaManager = new SchemaManager("rhqadmin", "rhqadmin", nodes, cqlPort);
} catch (Exception e) { if (null != ccm) { @@ -148,7 +153,10 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension { } else { try { String seed = System.getProperty("rhq.cassandra.seeds", "127.0.0.1|7299|9042"); - schemaManager = new SchemaManager("rhqadmin", "rhqadmin", seed); + nodes = parseNodeAddresses(seed); + cqlPort = parseNodeCqlPort(seed); + jmxPorts = parseNodeJmxPorts(seed); + schemaManager = new SchemaManager("rhqadmin", "rhqadmin", nodes, cqlPort);
} catch (Exception e) { throw new RuntimeException("External Cassandra initialization failed", e); @@ -157,7 +165,7 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension {
try { schemaManager.install(); - clusterInitService.waitForSchemaAgreement(nodes); + clusterInitService.waitForSchemaAgreement(nodes, jmxPorts); schemaManager.updateTopology(); } catch (Exception e) { if (null != ccm) { @@ -260,5 +268,58 @@ public class CCMSuiteDeploymentExtension implements LoadableExtension { throw new RuntimeException("Could not load defined deploymentClass: " + className, e); } } + + private String[] parseNodeAddresses(String s) { + String[] unparsedNodes = s.split(","); + + String[] nodes = new String[unparsedNodes.length]; + + for (int index = 0; index < 0; index++) { + String[] params = unparsedNodes[index].split("\|"); + if (params.length != 3) { + throw new IllegalArgumentException( + "Expected string of the form, hostname|jmxPort|nativeTransportPort: [" + s + "]"); + } + + nodes[index] = params[0]; + } + + return nodes; + } + + private int[] parseNodeJmxPorts(String s) { + String[] unparsedNodes = s.split(","); + + int[] jmxPorts = new int[unparsedNodes.length]; + + for (int index = 0; index < 0; index++) { + String[] params = unparsedNodes[index].split("\|"); + if (params.length != 3) { + throw new IllegalArgumentException( + "Expected string of the form, hostname|jmxPort|nativeTransportPort: [" + s + "]"); + } + + jmxPorts[index] = Integer.parseInt(params[1]); + } + + return jmxPorts; + } + + private int parseNodeCqlPort(String s) { + String[] unparsedNodes = s.split(","); + + for (String unparsedNode : unparsedNodes) { + String[] params = unparsedNode.split("\|"); + if (params.length != 3) { + throw new IllegalArgumentException( + "Expected string of the form, hostname|jmxPort|nativeTransportPort: [" + s + "]"); + } + + return Integer.parseInt(params[2]); + } + + throw new IllegalArgumentException("Seed property is not valid [" + s + "]"); + } + } } \ No newline at end of file diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/CassandraClusterManager.java b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/CassandraClusterManager.java index c8bb2ef..4a02e1d 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/CassandraClusterManager.java +++ b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/CassandraClusterManager.java @@ -46,7 +46,6 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
-import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.pluginapi.util.ProcessExecutionUtility; import org.rhq.core.system.OperatingSystemType; import org.rhq.core.system.ProcessExecution; @@ -68,6 +67,11 @@ public class CassandraClusterManager { private List<File> installedNodeDirs = new ArrayList<File>(); private Map<Integer, Process> nodeProcessMap = new HashMap<Integer, Process>();
+ private String[] nodes; + private int[] jmxPorts; + private int cqlPort; + + public CassandraClusterManager() { this(new DeploymentOptionsFactory().newDeploymentOptions()); } @@ -90,7 +94,28 @@ public class CassandraClusterManager { } }
- public List<StorageNode> createCluster() { + /** + * @return addresses of storage cluster nodes + */ + public String[] getNodes() { + return nodes; + } + + /** + * @return the JMX ports + */ + public int[] getJmxPorts() { + return jmxPorts; + } + + /** + * @return the CQL Port + */ + public int getCqlPort() { + return cqlPort; + } + + public void createCluster() { if (log.isDebugEnabled()) { log.debug("Installing embedded " + deploymentOptions.getNumNodes() + " node cluster to " + deploymentOptions.getClusterDir()); @@ -104,11 +129,10 @@ public class CassandraClusterManager { if (installedMarker.exists()) { log.info("It appears that the cluster already exists in " + clusterDir); log.info("Skipping cluster creation."); - return calculateNodes(); + getStorageClusterConfiguration(); } FileUtil.purge(clusterDir, false);
- List<StorageNode> nodes = new ArrayList<StorageNode>(deploymentOptions.getNumNodes()); String seeds = collectionToString(calculateLocalIPAddresses(deploymentOptions.getNumNodes())); Set<InetAddress> ipAddresses = null;
@@ -118,6 +142,10 @@ public class CassandraClusterManager { throw new RuntimeException("Failed to get cluster IP addresses", e); }
+ this.nodes = new String[deploymentOptions.getNumNodes()]; + this.jmxPorts = new int[deploymentOptions.getNumNodes()]; + this.cqlPort = deploymentOptions.getNativeTransportPort(); + for (int i = 0; i < deploymentOptions.getNumNodes(); ++i) { File basedir = new File(deploymentOptions.getClusterDir(), "node" + i); String address = getLocalIPAddress(i + 1); @@ -142,15 +170,11 @@ public class CassandraClusterManager { deployer.unzipDistro(); deployer.applyConfigChanges(); deployer.updateFilePerms(); - - StorageNode storageNode = new StorageNode(); - storageNode.setAddress(address); - storageNode.setJmxPort(deploymentOptions.getJmxPort() + i); - storageNode.setCqlPort(nodeOptions.getNativeTransportPort()); - nodes.add(storageNode); - deployer.updateStorageAuthConf(ipAddresses);
+ this.nodes[i] = address; + this.jmxPorts[i] = deploymentOptions.getJmxPort() + i; + installedNodeDirs.add(basedir); } catch (Exception e) { log.error("Failed to install node at " + basedir); @@ -162,7 +186,6 @@ public class CassandraClusterManager { } catch (IOException e) { log.warn("Failed to write installed file marker to " + installedMarker, e); } - return nodes; }
private void updateStorageAuthConf(File basedir) { @@ -210,16 +233,14 @@ public class CassandraClusterManager { return ipAddresses; }
- private List<StorageNode> calculateNodes() { - List<StorageNode> nodes = new ArrayList<StorageNode>(deploymentOptions.getNumNodes()); + private void getStorageClusterConfiguration() { + this.nodes = new String[deploymentOptions.getNumNodes()]; for (int i = 0; i < deploymentOptions.getNumNodes(); ++i) { - StorageNode storageNode = new StorageNode(); - storageNode.setAddress(getLocalIPAddress(i + 1)); - storageNode.setJmxPort(deploymentOptions.getJmxPort() + i); - storageNode.setCqlPort(deploymentOptions.getNativeTransportPort()); - nodes.add(storageNode); + this.nodes[i] = getLocalIPAddress(i + 1); + this.jmxPorts[i] = deploymentOptions.getJmxPort() + i; } - return nodes; + + this.cqlPort = deploymentOptions.getNativeTransportPort(); }
public void startCluster() { @@ -230,9 +251,9 @@ public class CassandraClusterManager { startCluster(getNodeIds());
if (waitForClusterToStart) { - List<StorageNode> nodes = calculateNodes(); + getStorageClusterConfiguration(); ClusterInitService clusterInitService = new ClusterInitService(); - clusterInitService.waitForClusterToStart(nodes, nodes.size(), 20); + clusterInitService.waitForClusterToStart(this.nodes, this.jmxPorts, this.nodes.length, 20); } }
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java index 83851c5..cbbfad5 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java +++ b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java @@ -28,7 +28,6 @@ package org.rhq.cassandra; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; @@ -42,8 +41,6 @@ import javax.management.remote.JMXServiceURL; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
-import org.rhq.core.domain.cloud.StorageNode; - /** * This class provides operations to ensure a cluster is initialized and in a consistent * state. It does not offer functionality for initializing a cluster but rather to make @@ -56,13 +53,25 @@ public final class ClusterInitService {
private final Log log = LogFactory.getLog(ClusterInitService.class);
- public boolean ping(List<StorageNode> storageNodes, int numHosts) { + private static final String JMX_CONNECTION_STRING = "service:jmx:rmi:///jndi/rmi://%s:%s/jmxrmi"; + + /** + * Pings the storage nodes to verify if they are available and native transport + * is running. + * + * @param storageNodes storage node addresses + * @param jmxPorts JMX ports + * @param numHosts minimum number of active hosts + * + * @return [true] cluster available with at least minimum number of hosts available, [false] otherwise + */ + public boolean ping(String[] storageNodes, int[] jmxPorts, int numHosts) { int connections = 0; long sleep = 100;
- for (StorageNode host : storageNodes) { + for (int index = 0; index < jmxPorts.length; index++) { try { - boolean isNativeTransportRunning = this.isNativeTransportRunning(host); + boolean isNativeTransportRunning = this.isNativeTransportRunning(storageNodes[index], jmxPorts[index]); if (isNativeTransportRunning) { ++connections; } @@ -71,7 +80,8 @@ public final class ClusterInitService { } } catch (Exception e) { if (log.isDebugEnabled()) { - log.debug("Unable to open JMX connection to cassandra node [" + host + "]", e); + log.debug("Unable to open JMX connection on port [" + jmxPorts[index] + "] to cassandra node [" + + storageNodes[index] + "]", e); } return false; } @@ -89,12 +99,12 @@ public final class ClusterInitService { * hosts. A runtime exception will be thrown after 10 failed retries. * <br/><br/> * After connecting to all nodes, this method will then sleep for a fixed delay. - * See {@link #waitForClusterToStart(java.util.List, int, int)} for details. - * - * @param hosts The cluster nodes to which a connection should be made + * See {@link #waitForClusterToStart(int, java.util.List, int)} for details. + * @param storageNodes The cluster nodes to which a connection should be made + * @param jmxPorts JMX port for each cluster node address */ - public void waitForClusterToStart(List<StorageNode> storageNodes) { - waitForClusterToStart(storageNodes, storageNodes.size(), 10); + public void waitForClusterToStart(String[] storageNodes, int jmxPorts[]) { + waitForClusterToStart(storageNodes, jmxPorts, storageNodes.length, 10); }
/** @@ -109,15 +119,14 @@ public final class ClusterInitService { * schema and to create the cassandra super user. Cassandra has a hard-coded delay of * 10 sceonds before it creates the super user, which means the rhq schema cannot be * created before that. - * - * @param hosts The cluster nodes to which a connection should be made * @param numHosts The number of hosts to which a successful connection has to be made * before returning. * @param retries The number of times to retry connecting. A runtime exception will be * thrown when the number of failed connections exceeds this value. + * @param hosts The cluster nodes to which a connection should be made */ - public void waitForClusterToStart(List<StorageNode> storageNodes, int numHosts, int retries) { - waitForClusterToStart(storageNodes, numHosts, 250, retries, 1); + public void waitForClusterToStart(String[] storageNodes, int jmxPorts[], int numHosts, int retries) { + waitForClusterToStart(storageNodes, jmxPorts, numHosts, 250, retries, 1); }
/** @@ -132,17 +141,16 @@ public final class ClusterInitService { * schema and to create the cassandra super user. Cassandra has a hard-coded delay of * 10 sceonds before it creates the super user, which means the rhq schema cannot be * created before that. - * - * @param hosts The cluster nodes to which a connection should be made * @param numHosts The number of hosts to which a successful connection has to be made * before returning. * @param delay The amount of time wait between attempts to make a connection * @param retries The number of times to retry connecting. A runtime exception will be * thrown when the number of failed connections exceeds this value. * @param initialWait The amount of seconds before first try. + * @param hosts The cluster nodes to which a connection should be made */ - public void waitForClusterToStart(List<StorageNode> storageNodes, int numHosts, long delay, int retries, - int initialWait) { + public void waitForClusterToStart(String[] storageNodes, int jmxPorts[], int numHosts, long delay, + int retries, int initialWait) { if (initialWait > 0) { try { if (log.isDebugEnabled()) { @@ -155,23 +163,28 @@ public final class ClusterInitService {
int connections = 0; int failedConnections = 0; - Queue<StorageNode> queue = new LinkedList<StorageNode>(storageNodes); - StorageNode storageNode = queue.poll(); + Queue<Integer> queue = new LinkedList<Integer>(); + for (int index = 0; index < storageNodes.length; index++) { + queue.add(index); + } + + Integer storageNodeIndex = queue.poll();
- while (storageNode != null) { + while (storageNodeIndex != null) { if (failedConnections >= retries) { throw new RuntimeException("Unable to verify that cluster nodes have started after " + failedConnections + " failed attempts"); } try { - boolean isNativeTransportRunning = this.isNativeTransportRunning(storageNode); + boolean isNativeTransportRunning = isNativeTransportRunning(storageNodes[storageNodeIndex], + jmxPorts[storageNodeIndex]); if (log.isDebugEnabled() && isNativeTransportRunning) { - log.debug("Successfully connected to cassandra node [" + storageNode + "]"); + log.debug("Successfully connected to cassandra node [" + storageNodes[storageNodeIndex] + "]"); } if (isNativeTransportRunning) { ++connections; } else { - queue.offer(storageNode); + queue.offer(storageNodeIndex); } if (connections == numHosts) { if (log.isDebugEnabled()) { @@ -186,9 +199,10 @@ public final class ClusterInitService { } } catch (Exception e) { ++failedConnections; - queue.offer(storageNode); + queue.offer(storageNodeIndex); if (log.isDebugEnabled()) { - log.debug("Unable to open JMX connection to cassandra node [" + storageNode + "].", e); + log.debug("Unable to open JMX connection on port [" + jmxPorts[storageNodeIndex] + + "] to cassandra node [" + storageNodes[storageNodeIndex] + "].", e); } else if (log.isInfoEnabled()) { log.debug("Unable to open connection to cassandra node."); } @@ -197,7 +211,7 @@ public final class ClusterInitService { Thread.sleep(delay); } catch (InterruptedException e) { } - storageNode = queue.poll(); + storageNodeIndex = queue.poll(); } }
@@ -209,8 +223,8 @@ public final class ClusterInitService { * * @param hosts The cluster nodes */ - public void waitForSchemaAgreement(List<StorageNode> storageNodes) throws Exception { - if (storageNodes == null) { + public void waitForSchemaAgreement(String[] storageNodes, int[] jmxPorts) throws Exception { + if (storageNodes == null || storageNodes.length == 0) { return; }
@@ -219,8 +233,8 @@ public final class ClusterInitService {
while (!schemaInAgreement) { Set<String> schemaVersions = new HashSet<String>(); - for (StorageNode host : storageNodes) { - String otherSchchemaVersion = getSchemaVersionForNode(host); + for (int index = 0; index < storageNodes.length; index++) { + String otherSchchemaVersion = getSchemaVersionForNode(storageNodes[index], jmxPorts[index]); if (otherSchchemaVersion != null) { schemaVersions.add(otherSchchemaVersion); } @@ -256,9 +270,9 @@ public final class ClusterInitService { } }
- public boolean isNativeTransportRunning(StorageNode storageNode) throws Exception { + public boolean isNativeTransportRunning(String storageNode, int jmxPort) throws Exception { Boolean nativeTransportRunning = false; - String url = storageNode.getJMXConnectionURL(); + String url = getJMXConnectionURL(storageNode, jmxPort); JMXServiceURL serviceURL = new JMXServiceURL(url); Map<String, String> env = new HashMap<String, String>(); JMXConnector connector = null; @@ -292,8 +306,8 @@ public final class ClusterInitService { return nativeTransportRunning; }
- private String getSchemaVersionForNode(StorageNode storageNode) throws Exception { - String url = storageNode.getJMXConnectionURL(); + private String getSchemaVersionForNode(String storageNode, int jmxPort) throws Exception { + String url = this.getJMXConnectionURL(storageNode, jmxPort); JMXServiceURL serviceURL = new JMXServiceURL(url); Map<String, String> env = new HashMap<String, String>(); JMXConnector connector = null; @@ -326,4 +340,17 @@ public final class ClusterInitService { } return null; } + + /** + * Constructs the JMX connection URL based on the node address and + * JMX port + * + * @param address + * @param jmxPort + * @return + */ + private String getJMXConnectionURL(String address, int jmxPort) { + String[] split = JMX_CONNECTION_STRING.split("%s"); + return split[0] + address + split[1] + jmxPort + split[2]; + } } \ No newline at end of file diff --git a/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java b/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java index f50535c..310d7a2 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java +++ b/modules/common/cassandra-ccm/cassandra-ccm-maven-plugin/src/main/java/org/rhq/cassandra/ccm/maven/DeployMojo.java @@ -26,7 +26,6 @@ package org.rhq.cassandra.ccm.maven;
import java.io.File; -import java.util.List;
import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; @@ -38,7 +37,6 @@ import org.rhq.cassandra.CassandraClusterManager; import org.rhq.cassandra.DeploymentOptions; import org.rhq.cassandra.DeploymentOptionsFactory; import org.rhq.cassandra.schema.SchemaManager; -import org.rhq.core.domain.cloud.StorageNode;
/** * @author John Sanda @@ -63,14 +61,14 @@ public class DeployMojo extends AbstractMojo {
long start = System.currentTimeMillis(); getLog().info("Creating " + numNodes + " cluster in " + clusterDir); - List<StorageNode> nodes = ccm.createCluster(); + ccm.createCluster();
getLog().info("Starting cluster nodes"); ccm.startCluster();
getLog().info("Installing RHQ schema"); SchemaManager schemaManager = new SchemaManager(deploymentOptions.getUsername(), - deploymentOptions.getPassword(), nodes); + deploymentOptions.getPassword(), ccm.getNodes(), ccm.getCqlPort());
try { schemaManager.install(); diff --git a/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java b/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java index a9292f7..48d047d 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java +++ b/modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java/org/rhq/cassandra/CCMTestNGListener.java @@ -27,7 +27,6 @@ package org.rhq.cassandra;
import java.io.File; import java.lang.reflect.Method; -import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -36,7 +35,6 @@ import org.testng.IInvokedMethodListener; import org.testng.ITestResult;
import org.rhq.cassandra.schema.SchemaManager; -import org.rhq.core.domain.cloud.StorageNode;
/** * @author John Sanda @@ -105,13 +103,15 @@ public class CCMTestNGListener implements IInvokedMethodListener { // we cannot initialize ccm here. ccm = new CassandraClusterManager(deploymentOptions); ClusterInitService clusterInitService = new ClusterInitService(); + ccm.createCluster();
- List<StorageNode> nodes = ccm.createCluster(); + String[] nodes = ccm.getNodes(); + int[] jmxPorts = ccm.getJmxPorts();
if (System.getProperty("rhq.cassandra.cluster.skip-shutdown") == null) { - for (StorageNode node : nodes) { + for (int index = 0; index < nodes.length; index++) { try { - if (clusterInitService.isNativeTransportRunning(node)) { + if (clusterInitService.isNativeTransportRunning(nodes[index], jmxPorts[index])) { throw new RuntimeException("A cluster is already running on the same ports."); } } catch (Exception e) { @@ -122,12 +122,13 @@ public class CCMTestNGListener implements IInvokedMethodListener { ccm.startCluster(false);
- clusterInitService.waitForClusterToStart(nodes, nodes.size(), 1500, 20, 2); + clusterInitService.waitForClusterToStart(nodes, jmxPorts, nodes.length, 20, 2, 1500);
- SchemaManager schemaManager = new SchemaManager(annotation.username(), annotation.password(), nodes); + SchemaManager schemaManager = new SchemaManager(annotation.username(), annotation.password(), nodes, + ccm.getCqlPort()); schemaManager.install(); if (annotation.waitForSchemaAgreement()) { - clusterInitService.waitForSchemaAgreement(nodes); + clusterInitService.waitForSchemaAgreement(nodes, jmxPorts); } schemaManager.updateTopology(); } diff --git a/modules/common/cassandra-schema/pom.xml b/modules/common/cassandra-schema/pom.xml index 6fb2915..077cdb9 100644 --- a/modules/common/cassandra-schema/pom.xml +++ b/modules/common/cassandra-schema/pom.xml @@ -13,16 +13,10 @@ <name>RHQ Cassandra Schema</name>
<dependencies> - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-cassandra-ccm-core</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-cassandra-util</artifactId> - <version>${project.version}</version> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>rhq-cassandra-util</artifactId> + <version>${project.version}</version> </dependency>
<dependency> @@ -36,13 +30,6 @@ </dependency>
<dependency> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-core-domain</artifactId> - <version>${project.version}</version> - </dependency> - - - <dependency> <groupId>com.datastax.cassandra</groupId> <artifactId>cassandra-driver-core</artifactId> <version>${cassandra.driver.version}</version> diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java index 7b8c520..7dcef1b 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java @@ -40,8 +40,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
import org.rhq.cassandra.util.ClusterBuilder; -import org.rhq.core.domain.cloud.StorageNode; -import org.rhq.core.util.StringUtil;
/** * @author Stefan Negrea @@ -71,13 +69,15 @@ abstract class AbstractManager { private Session session; private final String username; private final String password; - private List<StorageNode> nodes = new ArrayList<StorageNode>(); + private final int cqlPort; + private final String[] nodes; private final UpdateFile managementTasks;
- protected AbstractManager(String username, String password, List<StorageNode> nodes) { + protected AbstractManager(String username, String password, String[] nodes, int cqlPort) { try { this.username = username; this.password = password; + this.cqlPort = cqlPort; this.nodes = nodes; } catch (NoHostAvailableException e) { throw new RuntimeException("Unable create storage node session.", e); @@ -108,15 +108,11 @@ abstract class AbstractManager { protected void initClusterSession(String username, String password) { shutdownClusterConnection();
- String[] hostNames = new String[nodes.size()]; - for (int i = 0; i < hostNames.length; ++i) { - hostNames[i] = nodes.get(i).getAddress(); - }
- log.info("Initializing session to connect to " + StringUtil.arrayToString(hostNames)); + log.info("Initializing storage node session.");
- Cluster cluster = new ClusterBuilder().addContactPoints(hostNames).withCredentials(username, password) - .withPort(nodes.get(0).getCqlPort()).withCompression(Compression.NONE).build(); + Cluster cluster = new ClusterBuilder().addContactPoints(nodes).withCredentials(username, password) + .withPort(this.getCqlPort()).withCompression(Compression.NONE).build();
log.info("Cluster connection configured.");
@@ -140,7 +136,7 @@ abstract class AbstractManager { * @return cluster size */ protected int getClusterSize() { - return nodes.size(); + return nodes.length; }
/** @@ -158,6 +154,13 @@ abstract class AbstractManager { }
/** + * @return the cqlPort + */ + protected int getCqlPort() { + return cqlPort; + } + + /** * Runs a CQL query to check the existence of the RHQ user on the storage cluster. * * @return true if the RHQ user exists, false otherwise diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java index 1a82779..fdad697 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java @@ -25,7 +25,6 @@
package org.rhq.cassandra.schema;
-import java.util.ArrayList; import java.util.Arrays; import java.util.List;
@@ -34,8 +33,6 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout;
-import org.rhq.core.domain.cloud.StorageNode; - /** * @author John Sanda */ @@ -51,19 +48,29 @@ public class SchemaManager { */ private final String password;
- private final List<StorageNode> nodes = new ArrayList<StorageNode>(); + /** + * Node addresses + */ + private final String[] nodes;
/** * - * @param username The username RHQ will use to connect to the storage cluster. - * @param password The password RHQ will use to connect to the storage cluster. - * @param nodes A list of seeds nodes that are assumed to be already running and - * clustered prior to apply schema changes. The format for each node - * should be address|jmx_port|cql_port,address|jmx_port|cql_port. - * Each node consists of three fields that are pipe-delimited. */ - public SchemaManager(String username, String password, String... nodes) { - this(username, password, parseNodeInformation(nodes)); + private final int cqlPort; + + /** + * + * @param username The username RHQ will use to connect to the storage cluster + * @param password The password RHQ will use to connect to the storage cluster + * @param nodes A list of seeds nodes that are assumed to be already running and + * clustered prior to apply schema changes. + * @param cqlPort The native CQL port for the storage cluster + */ + public SchemaManager(String username, String password, String[] nodes, int cqlPort) { + this.username = username; + this.password = password; + this.cqlPort = cqlPort; + this.nodes = nodes; }
/** @@ -72,11 +79,13 @@ public class SchemaManager { * @param password The password RHQ will use to connect to the storage cluster. * @param nodes A list of seeds nodes that are assumed to be already running and * clustered prior to apply schema changes. + * @param cqlPort The native CQL port for the storage cluster */ - public SchemaManager(String username, String password, List<StorageNode> nodes) { + public SchemaManager(String username, String password, List<String> nodes, int cqlPort) { this.username = username; this.password = password; - this.nodes.addAll(nodes); + this.cqlPort = cqlPort; + this.nodes = nodes.toArray(new String[nodes.size()]); }
/** @@ -85,7 +94,7 @@ public class SchemaManager { * @throws Exception */ public void install() throws Exception { - VersionManager version = new VersionManager(username, password, nodes); + VersionManager version = new VersionManager(username, password, nodes, cqlPort); version.install(); }
@@ -96,7 +105,7 @@ public class SchemaManager { * @throws Exception */ public void checkCompatibility() throws Exception { - VersionManager version = new VersionManager(username, password, nodes); + VersionManager version = new VersionManager(username, password, nodes, cqlPort); version.checkCompatibility(); }
@@ -106,7 +115,7 @@ public class SchemaManager { * @throws Exception */ public void drop() throws Exception { - VersionManager version = new VersionManager(username, password, nodes); + VersionManager version = new VersionManager(username, password, nodes, cqlPort); version.drop(); }
@@ -118,7 +127,7 @@ public class SchemaManager { * @throws Exception */ public void updateTopology() throws Exception { - TopologyManager topology = new TopologyManager(username, password, nodes); + TopologyManager topology = new TopologyManager(username, password, nodes, cqlPort); topology.updateTopology(); }
@@ -127,28 +136,11 @@ public class SchemaManager { * * @return list of storage nodes */ - public List<StorageNode> getStorageNodes() { + protected String[] getStorageNodes() { return nodes; }
/** - * Parse raw string that contains the list of storage nodes. - * - * @param nodes list of storage nodes - * @return - */ - private static List<StorageNode> parseNodeInformation(String... nodes) { - List<StorageNode> parsedNodes = new ArrayList<StorageNode>(); - for (String node : nodes) { - StorageNode storageNode = new StorageNode(); - storageNode.parseNodeInformation(node); - parsedNodes.add(storageNode); - } - - return parsedNodes; - } - - /** * A main runner used for direct usage of the schema manager. * * @param args arguments @@ -164,19 +156,19 @@ public class SchemaManager { migratorLogging.setLevel(Level.ALL);
if (args.length < 4) { - System.out.println("Usage : command username password nodes..."); + System.out.println("Usage : command username password cqlPort nodes..."); System.out.println("\n"); System.out.println("Commands : install | drop | topology"); - System.out.println("Node format: hostname|jmxPort|cqlPort"); return; }
String command = args[0]; String username = args[1]; String password = args[2]; - String[] hosts = Arrays.copyOfRange(args, 3, args.length); + int cqlPort = Integer.parseInt(args[3]); + String[] hosts = Arrays.copyOfRange(args, 4, args.length);
- SchemaManager schemaManager = new SchemaManager(username, password, hosts); + SchemaManager schemaManager = new SchemaManager(username, password, hosts, cqlPort);
if ("install".equalsIgnoreCase(command)) { schemaManager.install(); diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java index 6c08faa..481c006 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/TopologyManager.java @@ -1,37 +1,33 @@ /* * - * * RHQ Management Platform - * * Copyright (C) 2005-2012 Red Hat, Inc. - * * All rights reserved. - * * - * * This program is free software; you can redistribute it and/or modify - * * it under the terms of the GNU General Public License, 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-2012 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, 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.cassandra.schema;
-import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
-import org.rhq.core.domain.cloud.StorageNode; - /** * @author Stefan Negrea */ @@ -56,8 +52,8 @@ class TopologyManager extends AbstractManager { } }
- public TopologyManager(String username, String password, List<StorageNode> nodes) { - super(username, password, nodes); + public TopologyManager(String username, String password, String[] nodes, int cqlPort) { + super(username, password, nodes, cqlPort); }
/** diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java index fe6ddf9..05cee25 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java @@ -25,7 +25,6 @@
package org.rhq.cassandra.schema;
-import java.util.List; import java.util.Properties; import java.util.UUID;
@@ -37,7 +36,6 @@ import org.apache.commons.logging.LogFactory; import org.rhq.cassandra.schema.exception.InstalledSchemaTooAdvancedException; import org.rhq.cassandra.schema.exception.InstalledSchemaTooOldException; import org.rhq.cassandra.schema.exception.SchemaNotInstalledException; -import org.rhq.core.domain.cloud.StorageNode;
/** * @author Stefan Negrea @@ -64,8 +62,8 @@ class VersionManager extends AbstractManager { } }
- public VersionManager(String username, String password, List<StorageNode> nodes) throws Exception { - super(username, password, nodes); + public VersionManager(String username, String password, String[] nodes, int cqlPort) throws Exception { + super(username, password, nodes, cqlPort); }
/** diff --git a/modules/common/cassandra-util/src/main/java/org/rhq/cassandra/util/ConfigEditor.java b/modules/common/cassandra-util/src/main/java/org/rhq/cassandra/util/ConfigEditor.java index 9fc389c..42e531f 100644 --- a/modules/common/cassandra-util/src/main/java/org/rhq/cassandra/util/ConfigEditor.java +++ b/modules/common/cassandra-util/src/main/java/org/rhq/cassandra/util/ConfigEditor.java @@ -1,8 +1,11 @@ package org.rhq.cassandra.util;
+import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.List; @@ -11,9 +14,6 @@ import java.util.Map; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml;
-import org.rhq.core.util.StringUtil; -import org.rhq.core.util.file.FileUtil; - /** * @author John Sanda */ @@ -57,7 +57,7 @@ public class ConfigEditor {
public void restore() { try { - FileUtil.copyFile(backupFile, configFile); + this.copyFile(backupFile, configFile); backupFile.delete(); yaml = null; config = null; @@ -70,7 +70,7 @@ public class ConfigEditor { private void createBackup() { backupFile = new File(configFile.getParent(), "." + configFile.getName() + ".bak"); try { - FileUtil.copyFile(configFile, backupFile); + this.copyFile(configFile, backupFile); } catch (IOException e) { throw new ConfigEditorException("Failed to create " + backupFile, e); } @@ -113,7 +113,16 @@ public class ConfigEditor { Map seedProvider = (Map) seedProviderList.get(0); List paramsList = (List) seedProvider.get("parameters"); Map params = (Map) paramsList.get(0); - params.put("seeds", StringUtil.arrayToString(seeds)); + + StringBuilder seedsString = new StringBuilder(); + for (int i = 0; i < seeds.length; i++) { + if (i > 0) { + seedsString.append(","); + } + + seedsString.append(seeds[i]); + } + params.put("seeds", seedsString.toString()); }
public Integer getNativeTransportPort() { @@ -132,4 +141,24 @@ public class ConfigEditor { config.put("storage_port", port); }
+ public static void copyFile(File inFile, File outFile) throws FileNotFoundException, IOException { + BufferedInputStream is = new BufferedInputStream(new FileInputStream(inFile)); + BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outFile)); + + int bufferSize = 32768; + try { + is = new BufferedInputStream(is, bufferSize); + byte[] buffer = new byte[bufferSize]; + for (int bytesRead = is.read(buffer); bytesRead != -1; bytesRead = is.read(buffer)) { + os.write(buffer, 0, bytesRead); + } + os.flush(); + } catch (IOException ioe) { + throw new RuntimeException("Stream data cannot be copied", ioe); + } finally { + os.close(); + is.close(); + } + } + } diff --git a/modules/common/cassandra-util/src/test/java/org/rhq/cassandra/util/ConfigEditorTest.java b/modules/common/cassandra-util/src/test/java/org/rhq/cassandra/util/ConfigEditorTest.java index 9c3cc16..d101fc2 100644 --- a/modules/common/cassandra-util/src/test/java/org/rhq/cassandra/util/ConfigEditorTest.java +++ b/modules/common/cassandra-util/src/test/java/org/rhq/cassandra/util/ConfigEditorTest.java @@ -3,10 +3,14 @@ package org.rhq.cassandra.util; import static java.util.Arrays.asList; import static org.testng.Assert.assertEquals;
+import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.lang.reflect.Method;
import org.apache.cassandra.config.Config; @@ -17,9 +21,6 @@ import org.yaml.snakeyaml.Loader; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml;
-import org.rhq.core.util.file.FileUtil; -import org.rhq.core.util.stream.StreamUtil; - /** * @author John Sanda */ @@ -33,14 +34,14 @@ public class ConfigEditorTest { public void initTestDir(Method test) throws Exception { File dir = new File(getClass().getResource(".").toURI()); basedir = new File(dir, getClass().getSimpleName() + "/" + test.getName()); - FileUtil.purge(basedir, true); + purge(basedir, true); basedir.mkdirs();
configFile = new File(basedir, "cassandra.yaml");
InputStream inputStream = getClass().getResourceAsStream("/cassandra.yaml"); FileOutputStream outputStream = new FileOutputStream(configFile); - StreamUtil.copy(inputStream, outputStream); + copyStreams(inputStream, outputStream); }
@Test @@ -119,4 +120,40 @@ public class ConfigEditorTest { return (Config) yaml.load(inputStream); }
+ private static void purge(File dir, boolean deleteIt) { + if (dir != null) { + if (dir.isDirectory()) { + File[] doomedFiles = dir.listFiles(); + if (doomedFiles != null) { + for (File doomedFile : doomedFiles) { + purge(doomedFile, true); // call this method recursively + } + } + } + + if (deleteIt) { + dir.delete(); + } + } + + return; + } + + public static void copyStreams(InputStream is, OutputStream os) throws FileNotFoundException, IOException { + int bufferSize = 32768; + try { + is = new BufferedInputStream(is, bufferSize); + byte[] buffer = new byte[bufferSize]; + for (int bytesRead = is.read(buffer); bytesRead != -1; bytesRead = is.read(buffer)) { + os.write(buffer, 0, bytesRead); + } + os.flush(); + } catch (IOException ioe) { + throw new RuntimeException("Stream data cannot be copied", ioe); + } finally { + os.close(); + is.close(); + } + } + } diff --git a/modules/common/drift/pom.xml b/modules/common/drift/pom.xml index 9500e8d..b1347ab 100644 --- a/modules/common/drift/pom.xml +++ b/modules/common/drift/pom.xml @@ -16,15 +16,23 @@
<dependencies> <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>test-utils</artifactId> - <version>${project.version}</version> - <scope>test</scope> + <groupId>${project.groupId}</groupId> + <artifactId>test-utils</artifactId> + <version>${project.version}</version> + <scope>test</scope> </dependency> + <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - </dependency> + <groupId>${project.groupId}</groupId> + <artifactId>rhq-core-domain</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> </dependencies>
<profiles> diff --git a/modules/common/filetemplate-bundle/pom.xml b/modules/common/filetemplate-bundle/pom.xml index b6c587e..8e60b26 100644 --- a/modules/common/filetemplate-bundle/pom.xml +++ b/modules/common/filetemplate-bundle/pom.xml @@ -15,6 +15,12 @@ <description>A library with the code common to the agent and server plugins for File Template Bundles</description>
<dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>rhq-core-domain</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency>
<dependency> <groupId>gnu-getopt</groupId> diff --git a/modules/common/jboss-as/pom.xml b/modules/common/jboss-as/pom.xml index a5d3255..16dd176 100644 --- a/modules/common/jboss-as/pom.xml +++ b/modules/common/jboss-as/pom.xml @@ -16,6 +16,13 @@
<dependencies> <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>rhq-core-domain</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> <groupId>ant</groupId> <artifactId>ant</artifactId> <version>1.6.5</version> diff --git a/modules/common/pom.xml b/modules/common/pom.xml index 45ba5c6..f957b0e 100644 --- a/modules/common/pom.xml +++ b/modules/common/pom.xml @@ -15,12 +15,6 @@ <description>parent POM for all RHQ common plugin libraries</description>
<dependencies> - <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-core-domain</artifactId> - <version>${project.version}</version> - <scope>provided</scope> <!-- by PC --> - </dependency>
</dependencies>
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml index 1c66dd6..70783f4 100644 --- a/modules/core/dbutils/pom.xml +++ b/modules/core/dbutils/pom.xml @@ -204,11 +204,6 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-core-domain</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.1.3</version> diff --git a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java index 5c8002a..56e2df0 100644 --- a/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java +++ b/modules/enterprise/server/installer/src/main/java/org/rhq/enterprise/server/installer/InstallerServiceImpl.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Matcher; @@ -39,6 +40,7 @@ import org.rhq.common.jbossas.client.controller.DatasourceJBossASClient; import org.rhq.common.jbossas.client.controller.DeploymentJBossASClient; import org.rhq.common.jbossas.client.controller.WebJBossASClient; import org.rhq.core.db.DatabaseTypeFactory; +import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.util.PropertiesFileUpdate; import org.rhq.core.util.exception.ThrowableUtil; import org.rhq.enterprise.server.installer.ServerInstallUtil.ExistingSchemaOption; @@ -501,7 +503,7 @@ public class InstallerServiceImpl implements InstallerService { ServerInstallUtil.storeServerDetails(serverProperties, clearTextDbPassword, serverDetails);
ServerInstallUtil.persistStorageNodesIfNecessary(serverProperties, clearTextDbPassword, - storageNodeSchemaManager.getStorageNodes()); + parseNodeInformation(serverProperties)); }
@Override @@ -1154,12 +1156,31 @@ public class InstallerServiceImpl implements InstallerService { } }
+ private List<StorageNode> parseNodeInformation(HashMap<String, String> serverProps) { + String[] nodes = serverProps.get("rhq.cassandra.seeds").split(","); + + List<StorageNode> parsedNodes = new ArrayList<StorageNode>(); + for (String node : nodes) { + StorageNode storageNode = new StorageNode(); + storageNode.parseNodeInformation(node); + parsedNodes.add(storageNode); + } + + return parsedNodes; + } + private SchemaManager createStorageNodeSchemaManager(HashMap<String, String> serverProps) { - String[] hosts = serverProps.get("rhq.cassandra.seeds").split(","); String username = serverProps.get("rhq.cassandra.username"); String password = serverProps.get("rhq.cassandra.password");
- return new SchemaManager(username, password, hosts); + List<StorageNode> storageNodes = this.parseNodeInformation(serverProps); + String[] nodes = new String[storageNodes.size()]; + for (int index = 0; index < storageNodes.size(); index++) { + nodes[index] = storageNodes.get(index).getAddress(); + } + int cqlPort = storageNodes.get(0).getCqlPort(); + + return new SchemaManager(username, password, nodes, cqlPort); }
private void writeInstalledFileMarker() throws Exception { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java index dbd599a..799abcc 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java @@ -121,7 +121,13 @@ public class StorageClientManagerBean { * @param storageNodes storage nodes */ private void checkSchemaCompability(String username, String password, List<StorageNode> storageNodes) { - SchemaManager schemaManager = new SchemaManager(username, password, storageNodes); + String[] nodes = new String[storageNodes.size()]; + for (int index = 0; index < storageNodes.size(); index++) { + nodes[index] = storageNodes.get(index).getAddress(); + } + int cqlPort = storageNodes.get(0).getCqlPort(); + + SchemaManager schemaManager = new SchemaManager(username, password, nodes, cqlPort); try { schemaManager.checkCompatibility(); } catch (Exception e) { diff --git a/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java b/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java index 40e00bf..a5a3994 100644 --- a/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java +++ b/modules/helpers/metrics-simulator/src/main/java/org/rhq/metrics/simulator/Simulator.java @@ -28,7 +28,6 @@ package org.rhq.metrics.simulator; import java.io.File; import java.io.IOException; import java.util.HashSet; -import java.util.List; import java.util.PriorityQueue; import java.util.Set; import java.util.concurrent.Executors; @@ -52,7 +51,6 @@ import org.rhq.cassandra.DeploymentOptions; import org.rhq.cassandra.DeploymentOptionsFactory; import org.rhq.cassandra.schema.SchemaManager; import org.rhq.cassandra.util.ClusterBuilder; -import org.rhq.core.domain.cloud.StorageNode; import org.rhq.metrics.simulator.plan.ClusterConfig; import org.rhq.metrics.simulator.plan.ScheduleGroup; import org.rhq.metrics.simulator.plan.SimulationPlan; @@ -84,17 +82,16 @@ public class Simulator implements ShutdownManager { } });
- List<StorageNode> nodes = initCluster(plan); - - createSchema(nodes); + initCluster(plan); + createSchema();
Session session; if (plan.getClientCompression() == null) { - session = createSession(nodes); + session = createSession(); } else { ProtocolOptions.Compression compression = Enum.valueOf(ProtocolOptions.Compression.class, plan.getClientCompression().toUpperCase()); - session = createSession(nodes, compression); + session = createSession(compression); }
StorageSession storageSession = new StorageSession(session); @@ -172,17 +169,16 @@ public class Simulator implements ShutdownManager { log.info("Shut down complete"); }
- private List<StorageNode> initCluster(SimulationPlan plan) { + private void initCluster(SimulationPlan plan) { try { - List<StorageNode> nodes = deployCluster(plan.getClusterConfig()); - waitForClusterToInitialize(nodes); - return nodes; + deployCluster(plan.getClusterConfig()); + waitForClusterToInitialize(); } catch (Exception e) { throw new RuntimeException("Failed to start simulator. Cluster initialization failed.", e); } }
- private List<StorageNode> deployCluster(ClusterConfig clusterConfig) throws IOException { + private void deployCluster(ClusterConfig clusterConfig) throws IOException { File clusterDir = new File(clusterConfig.getClusterDir(), "cassandra"); log.info("Deploying cluster to " + clusterDir); clusterDir.mkdirs(); @@ -200,10 +196,8 @@ public class Simulator implements ShutdownManager { deploymentOptions.load();
ccm = new CassandraClusterManager(deploymentOptions); - List<StorageNode> nodes = ccm.createCluster(); + ccm.createCluster(); ccm.startCluster(false); - - return nodes; }
private void shutdownCluster() { @@ -211,26 +205,25 @@ public class Simulator implements ShutdownManager { ccm.shutdownCluster(); }
- private void waitForClusterToInitialize(List<StorageNode> nodes) { + private void waitForClusterToInitialize() { log.info("Waiting for cluster to initialize"); ClusterInitService clusterInitService = new ClusterInitService(); - clusterInitService.waitForClusterToStart(nodes, nodes.size(), 1500, 20, 2); + clusterInitService.waitForClusterToStart(ccm.getNodes(), ccm.getJmxPorts(), ccm.getNodes().length, 20, 2, 1500); }
- private void createSchema(List<StorageNode> nodes) { + private void createSchema() { try { log.info("Creating schema"); - SchemaManager schemaManager = new SchemaManager("rhqadmin", "rhqadmin", nodes); + SchemaManager schemaManager = new SchemaManager("rhqadmin", "rhqadmin", ccm.getNodes(), ccm.getCqlPort()); schemaManager.install(); } catch (Exception e) { throw new RuntimeException("Failed to start simulator. An error occurred during schema creation.", e); } }
- private Session createSession(List<StorageNode> nodes) throws NoHostAvailableException { + private Session createSession() throws NoHostAvailableException { try { - Cluster cluster = new ClusterBuilder() - .addContactPoints(getHostNames(nodes)) + Cluster cluster = new ClusterBuilder().addContactPoints(ccm.getNodes()).withPort(ccm.getCqlPort()) .withCredentials("rhqadmin", "rhqadmin") .build();
@@ -244,13 +237,12 @@ public class Simulator implements ShutdownManager { } }
- private Session createSession(List<StorageNode> nodes, ProtocolOptions.Compression compression) + private Session createSession(ProtocolOptions.Compression compression) throws NoHostAvailableException { try { log.debug("Creating session using " + compression.name() + " compression");
- Cluster cluster = new ClusterBuilder() - .addContactPoints(getHostNames(nodes)) + Cluster cluster = new ClusterBuilder().addContactPoints(ccm.getNodes()).withPort(ccm.getCqlPort()) .withCredentials("cassandra", "cassandra") .withCompression(compression) .build(); @@ -264,6 +256,7 @@ public class Simulator implements ShutdownManager { } }
+ @SuppressWarnings("deprecation") private Session initSession(Cluster cluster) { NodeFailureListener listener = new NodeFailureListener(); for (Host host : cluster.getMetadata().getAllHosts()) { @@ -273,14 +266,6 @@ public class Simulator implements ShutdownManager { return cluster.connect("rhq"); }
- private String[] getHostNames(List<StorageNode> nodes) { - String[] hostnames = new String[nodes.size()]; - for (int i = 0; i < hostnames.length; ++i) { - hostnames[i] = nodes.get(i).getAddress(); - } - return hostnames; - } - private Set<Schedule> initSchedules(ScheduleGroup scheduleSet) { long nextCollection = System.currentTimeMillis(); Set<Schedule> schedules = new HashSet<Schedule>(); diff --git a/modules/plugins/rhq-storage/src/test/java/org/rhq/plugins/storage/StorageNodeComponentITest.java b/modules/plugins/rhq-storage/src/test/java/org/rhq/plugins/storage/StorageNodeComponentITest.java index 63517e1..50f8156 100644 --- a/modules/plugins/rhq-storage/src/test/java/org/rhq/plugins/storage/StorageNodeComponentITest.java +++ b/modules/plugins/rhq-storage/src/test/java/org/rhq/plugins/storage/StorageNodeComponentITest.java @@ -150,9 +150,11 @@ public class StorageNodeComponentITest { storageNode.parseNodeInformation("127.0.0.1|7399|9142");
ClusterInitService clusterInitService = new ClusterInitService(); - clusterInitService.waitForClusterToStart(asList(storageNode)); + clusterInitService.waitForClusterToStart(new String[] { storageNode.getAddress() }, + new int[] { storageNode.getJmxPort() });
- SchemaManager schemaManager = new SchemaManager("rhqadmin", "rhqadmin", "127.0.0.1|7399|9142"); + SchemaManager schemaManager = new SchemaManager("rhqadmin", "rhqadmin", + new String[] { storageNode.getAddress() }, storageNode.getCqlPort()); schemaManager.install(); schemaManager.updateTopology(); }
commit f86a0777fa4cf7f3cacccca6e3eff9cbd9e49b7e Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 16:14:23 2013 -0400
shortening mode name so we now have ADD_MAINTENANCE and REMOVE_MAINTENANCE
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index e0f278d..aac8cb6 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -247,7 +247,7 @@ public class StorageNode implements Serializable { return Status.INSTALLED; } if (operationMode == OperationMode.ANNOUNCE || operationMode == OperationMode.BOOTSTRAP || - operationMode == OperationMode.ADD_NODE_MAINTENANCE) { + operationMode == OperationMode.ADD_MAINTENANCE) { if (errorMessage == null && failedOperation == null) { return Status.JOINING; } else { @@ -280,7 +280,7 @@ public class StorageNode implements Serializable { "gossip from its IP address."), BOOTSTRAP("The storage is installed but not yet part of the cluster. It is getting bootstrapped into the " + "cluster"), - ADD_NODE_MAINTENANCE("The storage node is running and is preparing to undergo routine maintenance that is " + + ADD_MAINTENANCE("The storage node is running and is preparing to undergo routine maintenance that is " + "necessary when a new node joins the cluster."), REMOVE_MAINTENANCE("The storage node is no longer part of the cluster. Remaining storage node are " + "undergoing cluster maintenance due to the topology change."), diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 55593d3..4d4fd17 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -246,7 +246,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN reset(); storageNodeOperationsHandler.bootstrapStorageNode(subject, storageNode); break; - case ADD_NODE_MAINTENANCE: + case ADD_MAINTENANCE: reset(); storageNodeOperationsHandler.performAddNodeMaintenance(subject, storageNode); default: @@ -272,7 +272,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN reset(); storageNodeOperationsHandler.unannounceStorageNode(subject, storageNode); break; - case ADD_NODE_MAINTENANCE: + case ADD_MAINTENANCE: case NORMAL: case DECOMMISSION: reset(); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index b619e72..b068734 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -34,7 +34,6 @@ import org.rhq.enterprise.server.auth.SessionManager; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal; import org.rhq.enterprise.server.operation.OperationManagerLocal; -import org.rhq.enterprise.server.resource.ResourceFactoryManagerLocal; import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.server.metrics.StorageSession;
@@ -193,7 +192,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
@Override public void performAddNodeMaintenance(Subject subject, StorageNode storageNode) { - storageNode.setOperationMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + storageNode.setOperationMode(StorageNode.OperationMode.ADD_MAINTENANCE); List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) .getResultList(); @@ -294,7 +293,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa String msg = "Aborting storage node deployment due to unexpected error while performing add node " + "maintenance."; log.error(msg, e); - storageNodeOperationsHandler.logError(StorageNode.OperationMode.ADD_NODE_MAINTENANCE, msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.ADD_MAINTENANCE, msg, e); } } else if (operationHistory.getOperationDefinition().getName().equals("decommission")) { try { @@ -435,11 +434,11 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // nothing to do here return; case CANCELED: - newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); deploymentOperationCanceled(storageNode, resourceOperationHistory, newStorageNode); return; case FAILURE: - newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); deploymentOperationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS @@ -450,7 +449,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (nextNode == null) { log.info("Finished running add node maintenance on all cluster nodes"); // TODO replace this with an UPDATE statement - newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_MAINTENANCE); newStorageNode.setOperationMode(StorageNode.OperationMode.NORMAL); } else { Configuration parameters = resourceOperationHistory.getParameters();
commit dd85d556fcf2b3e5bf34028d2607d2ccde86853f Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 15:51:14 2013 -0400
prepareForBootstrap operation should continue if the storage node is already stopped
Previously the prepareForShutdown operation would fail if the shutdown operation fails which will happen if the node is already stopped. There is no reason to fail the prepareForShutdown operation here because we want the node shut down. And if C* bootstrapping previously failed, the storage node is likely down.
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java index 7455f5e..2974beb 100644 --- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java +++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java @@ -290,6 +290,8 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper }
private OperationResult uninstall() { + log.info("Uninstalling storage node at " + getResourceContext().getResourceKey()); + OperationResult result = new OperationResult(); OperationResult shutdownResult = shutdownIfNecessary(); if (shutdownResult.getErrorMessage() != null) { @@ -363,14 +365,13 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper OperationResult result = new OperationResult();
log.info("Stopping storage node"); - OperationResult stopNodeResult = shutdownStorageNode(); - if (stopNodeResult.getErrorMessage() != null) { - log.error("Failed to stop storage node " + this + " Cannot prepare the node for bootstrap which means " + - "that the storage node cannot join the cluster. Make sure the storage node is not running and retry " + - "the operation"); - result.setErrorMessage("Failed to stop storage node. Cannot prepare the node for bootstrap which means " + - "that it cannot join the cluster. Make sure that the node is not running and retry the operation. " + - "Stopping the storage node failed with this error: " + stopNodeResult.getErrorMessage()); + OperationResult shutdownResult = shutdownIfNecessary(); + if (shutdownResult.getErrorMessage() != null) { + log.error("Failed to stop storage node " + getResourceContext().getResourceKey() + ". The storage node " + + "must be shut down in order for the changes made by this operation to take effect."); + result.setErrorMessage("Failed to stop the storage node. The storage node must be shut down in order " + + "for the changes made by this operation to take effect. The attempt to stop shut down the storage " + + "node failed with this error: " + shutdownResult.getErrorMessage()); return result; }
commit dc8fe178b0b24d756dc1fdddeafceb8ea9dc0ea0 Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 15:25:55 2013 -0400
fixing typo in api change justification
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index ea3b340..b5a4357 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -74,7 +74,7 @@ <difference> <className>org/rhq/enterprise/server/cloud/StorageNodeManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>void unDeployStorageNode(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.cloud.StorageNode)</method> + <method>void undeployStorageNode(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.cloud.StorageNode)</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
commit 33597f038d10783c15ff62727b9c2d8a17570633 Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 15:20:04 2013 -0400
refactor common operation scheduling code into a util method
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index f2fc108..b619e72 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -103,16 +103,11 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Announcing " + newStorageNode + " to cluster node " + clusterNode); } - ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(clusterNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("announce"); + Configuration parameters = new Configuration(); parameters.put(addresses); - schedule.setParameters(parameters);
- operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, clusterNode, parameters, "announce"); }
@Override @@ -129,16 +124,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
private void unannounceStorageNode(Subject subject, StorageNode clusterNode, PropertyList addresses) { - ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(clusterNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("unannounce"); Configuration parameters = new Configuration(); parameters.put(addresses); - schedule.setParameters(parameters);
- operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, clusterNode, parameters, "unannounce"); }
@Override @@ -150,15 +139,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (storageNode.getResource() == null) { finishUninstall(subject, storageNode); } else { - ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(storageNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("uninstall"); - Configuration parameters = new Configuration(); - schedule.setParameters(parameters); - - operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, storageNode, new Configuration(), "uninstall"); } }
@@ -183,14 +164,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // queue up storage nodes during cluster maintenance operations. storageNode.setMaintenancePending(runRepair);
- ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setOperationName("decommission"); - schedule.setResource(storageNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setParameters(new Configuration()); - - operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, storageNode, new Configuration(), "decommission"); }
@Override @@ -238,21 +212,12 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Running addNodeMaintenance for storage node " + storageNode); } + Configuration params = new Configuration(); + params.put(seedsList); + params.put(new PropertySimple(RUN_REPAIR_PROPERTY, runRepair)); + params.put(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.TRUE));
- ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(storageNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("addNodeMaintenance"); - - Configuration config = new Configuration(); - config.put(seedsList); - config.put(new PropertySimple(RUN_REPAIR_PROPERTY, runRepair)); - config.put(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.TRUE)); - - schedule.setParameters(config); - - operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, storageNode, params, "addNodeMaintenance"); }
@Override @@ -286,21 +251,12 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Running remove node maintenance for storage node " + storageNode); } + Configuration params = new Configuration(); + params.put(seedsList); + params.put(new PropertySimple(RUN_REPAIR_PROPERTY, runRepair)); + params.put(new PropertySimple(UPDATE_SEEDS_LIST, true));
- ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(storageNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("removeNodeMaintenance"); - - Configuration config = new Configuration(); - config.put(seedsList); - config.put(new PropertySimple(RUN_REPAIR_PROPERTY, runRepair)); - config.put(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.TRUE)); - - schedule.setParameters(config); - - operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, storageNode, params, "removeNodeMaintenance"); }
@Override @@ -578,7 +534,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa break; default: // SUCCESS log.info("Successfully uninstalled " + storageNode + " from disk"); - uninstall(getSubject(operationHistory), storageNode); + finishUninstall(getSubject(operationHistory), storageNode); } }
@@ -701,22 +657,13 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Preparing to bootstrap " + storageNode + " into cluster..."); } - - ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(storageNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("prepareForBootstrap"); - StorageClusterSettings clusterSettings = storageClusterSettingsManager.getClusterSettings(subject); Configuration parameters = new Configuration(); parameters.put(new PropertySimple("cqlPort", clusterSettings.getCqlPort())); parameters.put(new PropertySimple("gossipPort", clusterSettings.getGossipPort())); parameters.put(addresses);
- schedule.setParameters(parameters); - - operationManager.scheduleResourceOperation(subject, schedule); + scheduleOperation(subject, storageNode, parameters, "prepareForBootstrap"); }
private StorageNode takeFromMaintenanceQueue() { @@ -832,6 +779,19 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return value; }
+ private void scheduleOperation(Subject subject, StorageNode storageNode, Configuration parameters, + String operation) { + ResourceOperationSchedule schedule = new ResourceOperationSchedule(); + schedule.setResource(storageNode.getResource()); + schedule.setJobTrigger(JobTrigger.createNowTrigger()); + schedule.setSubject(subject); + schedule.setOperationName(operation); + schedule.setParameters(parameters); + + operationManager.scheduleResourceOperation(subject, schedule); + + } + private PropertyList createPropertyListOfAddresses(String propertyName, List<StorageNode> nodes) { PropertyList list = new PropertyList(propertyName); for (StorageNode storageNode : nodes) {
commit 50197e1e89d1382dce4fd7e9f703920fd239aec1 Author: John Sanda jsanda@redhat.com Date: Mon Aug 19 14:33:08 2013 -0400
fixing API check for new undeploy method in remote API
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 58bd618..ea3b340 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -72,6 +72,13 @@ </difference>
<difference> + <className>org/rhq/enterprise/server/cloud/StorageNodeManagerRemote</className> + <differenceType>7012</differenceType> <!-- method added to an interface --> + <method>void unDeployStorageNode(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.cloud.StorageNode)</method> + <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> + </difference> + + <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void assignBundlesToBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method>
commit 6ef8696c1d2c46571efcf638b0416d06fe3cffc5 Author: Jirka Kremser jkremser@redhat.com Date: Mon Aug 19 19:41:08 2013 +0200
Adding the support for storage node (un)deployment in coregui.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java index d1ea625..c49f697 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java @@ -124,7 +124,7 @@ public class StorageNodeAdminView extends EnhancedVLayout implements Bookmarkabl public void onFailure(Throwable caught) { Message message = new Message("Unable to render storage node alert view: " + caught.getMessage(), Message.Severity.Warning); - CoreGUI.goToView(VIEW_ID.getName(), message); + CoreGUI.goToView(StorageNodeTableView.VIEW_PATH, message); }
@Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java index 685fb5d..9ee4f28 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java @@ -31,6 +31,7 @@ import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDat import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_MTIME; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_OPERATION_MODE; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_RESOURCE_ID; +import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_STATUS;
import java.util.ArrayList; import java.util.List; @@ -63,7 +64,6 @@ import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.StorageNodeLoadCompositeDatasourceField; import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter; 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.Log; import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient; import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; @@ -144,7 +144,7 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit // cqlField.setHidden(true); // fields.add(cqlField);
- field = FIELD_OPERATION_MODE.getListGridField("90"); + field = FIELD_STATUS.getListGridField("90"); field.setCellFormatter(new CellFormatter() { public String format(Object value, ListGridRecord listGridRecord, int i, int i1) { if (listGridRecord.getAttribute(FIELD_ERROR_MESSAGE.propertyName()) != null @@ -154,6 +154,7 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit return value.toString(); } }); + field.setShowHover(true); field.setHoverCustomizer(new HoverCustomizer() { public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) { @@ -235,6 +236,7 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit record.setAttribute(FIELD_JMX_PORT.propertyName(), node.getJmxPort()); record.setAttribute(FIELD_CQL_PORT.propertyName(), node.getCqlPort()); record.setAttribute(FIELD_OPERATION_MODE.propertyName(), node.getOperationMode()); + record.setAttribute(FIELD_STATUS.propertyName(), node.getStatus()); record.setAttribute(FIELD_ERROR_MESSAGE.propertyName(), node.getErrorMessage()); if (node.getFailedOperation() != null && node.getFailedOperation().getResource() != null) { ResourceOperationHistory operationHistory = node.getFailedOperation(); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java index 04a1767..ada97fa 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java @@ -40,6 +40,8 @@ public enum StorageNodeDatasourceField {
FIELD_OPERATION_MODE("operationMode", CoreGUI.getMessages().view_adminTopology_server_mode()),
+ FIELD_STATUS("status", "Status"), + FIELD_MEMORY("memory", "Memory"),
FIELD_DISK("disk", "Disk"), diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java index 4055e6f..f5de561 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java @@ -77,6 +77,9 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message; public class StorageNodeDetailView extends EnhancedVLayout implements BookmarkableView {
private final int storageNodeId; + +// String path = StorageNodeAdminView.VIEW_PATH + "/" + storageNodeId; +// CoreGUI.goToView(path, message);
private static final int SECTION_COUNT = 3; private final SectionStack sectionStack; @@ -121,9 +124,7 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab new AsyncCallback<PageList<StorageNode>>() { public void onSuccess(final PageList<StorageNode> storageNodes) { if (storageNodes == null || storageNodes.isEmpty() || storageNodes.size() != 1) { - CoreGUI.getErrorHandler().handleError( - MSG.view_adminTopology_message_fetchServerFail(String.valueOf(storageNodeId))); - initSectionCount = SECTION_COUNT; + onFailure(new Exception("No storage nodes have been found.")); } final StorageNode node = storageNodes.get(0); header.setContents("<div style='text-align: center; font-weight: bold; font-size: medium;'> Storage Node (" @@ -166,6 +167,7 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab Message message = new Message(MSG.view_configurationHistoryDetails_error_loadFailure(), Message.Severity.Warning); initSectionCount = SECTION_COUNT; + CoreGUI.getMessageCenter().notify(message); }
@Override @@ -199,7 +201,10 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab new AsyncCallback<Map<String, List<MeasurementDataNumericHighLowComposite>>>() { @Override public void onFailure(Throwable caught) { - + Message message = new Message("Unable to fetch storage node load data.", + Message.Severity.Warning); + initSectionCount = SECTION_COUNT; + CoreGUI.getMessageCenter().notify(message); }
@Override @@ -357,7 +362,6 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab ResourceOperationHistory operationHistory = storageNode.getFailedOperation(); String value = LinkManager.getSubsystemResourceOperationHistoryLink(operationHistory.getResource().getId(), operationHistory.getId()); - // String value = "#Resource/" + operationHistory.getResource().getId() + "/Operations/History/" + operationHistory.getId()); lastOperation = new StaticTextItem("lastOp", "Operation"); lastOperation.setValue(LinkManager.getHref(value, operationHistory.getOperationDefinition() .getDisplayName())); @@ -389,7 +393,6 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab loadLayout.setWidth100(); LayoutSpacer spacer = new LayoutSpacer(); spacer.setHeight(10); -// HTMLFlow loadLabel = new HTMLFlow("<span style='font-weight:bold'>Status</span>"); HTMLFlow loadLabel = new HTMLFlow("Status"); loadLabel.addStyleName("formTitle"); loadLabel.setTooltip("Contains selected metrics collected for last 8 hours."); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java index 84c1586..50cb614 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java @@ -20,7 +20,7 @@ package org.rhq.enterprise.gui.coregui.client.admin.storage;
import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_ADDRESS; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_ALERTS; -import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_RESOURCE_ID; +import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.*;
import java.util.ArrayList; import java.util.Arrays; @@ -42,6 +42,7 @@ import com.smartgwt.client.widgets.grid.ListGridField; import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNode.OperationMode; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.LinkManager; @@ -85,7 +86,7 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { protected void doOnDraw() { super.doOnDraw(); // commenting out this call, because it caused UI to freeze -// scheduleUnacknowledgedAlertsPollingJob(getListGrid()); + // scheduleUnacknowledgedAlertsPollingJob(getListGrid()); }
@Override @@ -204,6 +205,80 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> {
private void showCommonActions() { addInvokeOperationsAction(); + addDeployAction(); + addUndeployAction(); + } + + private void addUndeployAction() { + final ParametrizedMessage question = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Are you sure, you want to run the undeploy operation on selected nodes: " + param[0] + + " ? It may take a while to complete."; + } + }; + final ParametrizedMessage success = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Starting the undeploy operation on storage nodes " + param[0]; + } + }; + final ParametrizedMessage failure = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Invoking the undeploy operation failed for storage nodes " + param[0] + " ids: " + param[1]; + } + }; + + addTableAction("Undeploy Selected", null, new AuthorizedTableAction(this, TableActionEnablement.SINGLE, + Permission.MANAGE_SETTINGS) { + + @Override + public boolean isEnabled(ListGridRecord[] selection) { + return StorageNodeTableView.this.isUndeployable(super.isEnabled(selection), selection); + } + + @Override + public void executeAction(final ListGridRecord[] selections, Object actionValue) { + executeBulkAction(selections, actionValue, question, success, failure, StorageNodeOperation.UNDEPLOY); + } + }); + } + + private void addDeployAction() { + final ParametrizedMessage question = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Are you sure, you want to run the deploy operation on selected nodes: " + param[0] + + " ? It may take a while to complete."; + } + }; + final ParametrizedMessage success = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Starting the deploy operation on storage nodes " + param[0]; + } + }; + final ParametrizedMessage failure = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Invoking the deploy operation failed for storage nodes " + param[0] + " ids: " + param[1]; + } + }; + + addTableAction("Deploy Selected", null, new AuthorizedTableAction(this, TableActionEnablement.SINGLE, + Permission.MANAGE_SETTINGS) { + + @Override + public boolean isEnabled(ListGridRecord[] selection) { + return StorageNodeTableView.this.isDeployable(super.isEnabled(selection), selection); + } + + @Override + public void executeAction(final ListGridRecord[] selections, Object actionValue) { + executeBulkAction(selections, actionValue, question, success, failure, StorageNodeOperation.DEPLOY); + } + }); }
private void addInvokeOperationsAction() { @@ -213,7 +288,6 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { operationsMap.put("Restart", "restart"); operationsMap.put("Disable Debug Mode", "stopRPCServer"); operationsMap.put("Enable Debug Mode", "startRPCServer"); - // operationsMap.put("Decommission", "decommission");
addTableAction(MSG.common_title_operation(), null, operationsMap, new AuthorizedTableAction(this, TableActionEnablement.ANY, Permission.MANAGE_SETTINGS) { @@ -221,77 +295,129 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { @Override public boolean isEnabled(ListGridRecord[] selection) { return StorageNodeTableView.this.isEnabled(super.isEnabled(selection), selection); - }; + }
@Override public void executeAction(final ListGridRecord[] selections, Object actionValue) { - final String operationName = (String) actionValue; - final List<String> selectedAddresses = getSelectedAddresses(selections); - // String message = MSG.view_adminTopology_message_setModeConfirm(selectedAddresses.toString(), mode.name()); - SC.ask("Are you sure, you want to run operation " + operationName + "?", new BooleanCallback() { - public void execute(Boolean confirmed) { - if (confirmed) { - final CountDownLatch latch = CountDownLatch.create(selections.length, new Command() { - @Override - public void execute() { - // Message msg = new Message(MSG.view_adminTopology_message_setMode( - // String.valueOf(selections.length), mode.name()), Message.Severity.Info); - Message msg = new Message("Operation" + operationName - + " was successfully scheduled for resources with ids" - + Arrays.asList(getSelectedIds(selections)), Message.Severity.Info); - CoreGUI.getMessageCenter().notify(msg); - refreshTableInfo(); - } - }); - boolean isStopStartOrRestart = Arrays.asList("start", "shutdown", "restart").contains( - operationName); - for (ListGridRecord storageNodeRecord : selections) { - // NFE should never happen, because of the condition for table action enablement - int resourceId = storageNodeRecord.getAttributeAsInt(FIELD_RESOURCE_ID.propertyName()); - if (isStopStartOrRestart) { - // start, stop or restart the storage node - GWTServiceLookup.getOperationService().scheduleResourceOperation(resourceId, - operationName, null, "Run by Storage Node Administrations UI", 0, - new AsyncCallback<Void>() { - public void onSuccess(Void result) { - latch.countDown(); - } - - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError( - "Scheduling operation " + operationName - + " failed for resources with ids" - + Arrays.asList(getSelectedIds(selections)) + " " - + caught.getMessage(), caught); - latch.countDown(); - refreshTableInfo(); - } - }); + ParametrizedMessage question = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Are you sure, you want to run operation " + param[0] + "?"; + } + }; + ParametrizedMessage success = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Operation" + param[0] + " was successfully scheduled for storage nodes " + param[1]; + } + }; + ParametrizedMessage failure = new ParametrizedMessage() { + @Override + public String getMessage(String... param) { + return "Scheduling operation " + param[0] + " failed for storage nodes " + param[1]; + } + }; + executeBulkAction(selections, actionValue, question, success, failure, StorageNodeOperation.OTHER); + } + }); + } + + private enum StorageNodeOperation { + DEPLOY, UNDEPLOY, OTHER + } + + private interface ParametrizedMessage { + String getMessage(String... param); + } + + private void executeBulkAction(final ListGridRecord[] selections, Object actionValue, ParametrizedMessage question, + final ParametrizedMessage success, final ParametrizedMessage failure, final StorageNodeOperation operationType) { + final String operationName = (String) actionValue; + final List<String> selectedAddresses = getSelectedAddresses(selections); + SC.ask(question.getMessage(selectedAddresses.toString()), new BooleanCallback() { + public void execute(Boolean confirmed) { + if (confirmed) { + final CountDownLatch latch = CountDownLatch.create(selections.length, new Command() { + @Override + public void execute() { + String msgString = null; + if (operationType == StorageNodeOperation.OTHER) { + msgString = success.getMessage(operationName, selectedAddresses.toString()); + } else { + msgString = success.getMessage(selectedAddresses.toString()); + } + Message msg = new Message(msgString, Message.Severity.Info); + CoreGUI.getMessageCenter().notify(msg); + refreshTableInfo(); + } + }); + boolean isStopStartOrRestart = Arrays.asList("start", "shutdown", "restart") + .contains(operationName); + for (ListGridRecord storageNodeRecord : selections) { + // NFE should never happen, because of the condition for table action enablement + int resourceId = storageNodeRecord.getAttributeAsInt(FIELD_RESOURCE_ID.propertyName()); + if (isStopStartOrRestart) { + // start, stop or restart the storage node + GWTServiceLookup.getOperationService().scheduleResourceOperation(resourceId, operationName, + null, "Run by Storage Node Administrations UI", 0, new AsyncCallback<Void>() { + public void onSuccess(Void result) { + latch.countDown(); + } + + public void onFailure(Throwable caught) { + String msg = failure.getMessage(operationName, + selectedAddresses + " " + caught.getMessage()); + CoreGUI.getErrorHandler().handleError(msg, caught); + latch.countDown(); + refreshTableInfo(); + } + }); + } else { + if (operationType != StorageNodeOperation.OTHER) { // (un)deploy + AsyncCallback<Void> callback = new AsyncCallback<Void>() { + public void onSuccess(Void result) { + latch.countDown(); + } + + public void onFailure(Throwable caught) { + String msg = failure.getMessage( + selectedAddresses.toString(), + Arrays.asList(getSelectedIds(selections)).toString() + " " + + caught.getMessage()); + CoreGUI.getErrorHandler().handleError(msg, caught); + latch.countDown(); + refreshTableInfo(); + } + }; + int storageNodeId = storageNodeRecord.getAttributeAsInt("id"); + StorageNode node = new StorageNode(storageNodeId); + if (operationType == StorageNodeOperation.DEPLOY) { + GWTServiceLookup.getStorageService().deployStorageNode(node, callback); } else { - // invoke the operation on the storage service resource - GWTServiceLookup.getStorageService().invokeOperationOnStorageService(resourceId, - operationName, new AsyncCallback<Void>() { - public void onSuccess(Void result) { - latch.countDown(); - } - - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError( - "Scheduling operation " + operationName - + " failed for resources with ids" - + Arrays.asList(getSelectedIds(selections)) + " " - + caught.getMessage(), caught); - latch.countDown(); - refreshTableInfo(); - } - }); + GWTServiceLookup.getStorageService().undeployStorageNode(node, callback); } + } else { + // invoke the operation on the storage service resource + GWTServiceLookup.getStorageService().invokeOperationOnStorageService(resourceId, + operationName, new AsyncCallback<Void>() { + public void onSuccess(Void result) { + latch.countDown(); + } + + public void onFailure(Throwable caught) { + String msg = failure.getMessage(operationName, selectedAddresses + " " + + caught.getMessage()); + CoreGUI.getErrorHandler().handleError(msg, caught); + latch.countDown(); + refreshTableInfo(); + } + }); } - } else { - refreshTableInfo(); } } - }); + } else { + refreshTableInfo(); + } } }); } @@ -331,6 +457,33 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { return true; }
+ private boolean isDeployable(boolean parentsOpinion, ListGridRecord[] selection) { + if (!parentsOpinion || !isEnabled(parentsOpinion, selection)) { + return false; + } + for (ListGridRecord storageNodeRecord : selection) { + if ("NORMAL".equals(storageNodeRecord.getAttributeAsString(FIELD_STATUS.propertyName())) + || "JOINING".equals(storageNodeRecord.getAttributeAsString(FIELD_STATUS.propertyName())) + || "LEAVING".equals(storageNodeRecord.getAttributeAsString(FIELD_STATUS.propertyName()))) { + return false; + } + } + return true; + } + + private boolean isUndeployable(boolean parentsOpinion, ListGridRecord[] selection) { + if (!parentsOpinion || !isEnabled(parentsOpinion, selection)) { + return false; + } + for (ListGridRecord storageNodeRecord : selection) { + if ("JOINING".equals(storageNodeRecord.getAttributeAsString(FIELD_STATUS.propertyName())) + || "LEAVING".equals(storageNodeRecord.getAttributeAsString(FIELD_STATUS.propertyName()))) { + return false; + } + } + return true; + } + @Override protected String getBasePath() { return VIEW_PATH; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java index 72f17b18..9470302 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java @@ -27,6 +27,7 @@ import java.util.Map;
import com.google.gwt.user.client.rpc.RemoteService;
+import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeConfigurationComposite; @@ -92,4 +93,8 @@ public interface StorageGWTService extends RemoteService { StorageClusterSettings retrieveClusterSettings() throws RuntimeException;
void updateClusterSettings(StorageClusterSettings clusterSettings) throws RuntimeException; + + void undeployStorageNode(StorageNode storageNode) throws RuntimeException; + + void deployStorageNode(StorageNode storageNode) throws RuntimeException; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java index ae18075..5548285 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map;
+import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeConfigurationComposite; @@ -201,5 +202,23 @@ public class StorageGWTServiceImpl extends AbstractGWTServiceImpl implements Sto } catch (Throwable t) { throw getExceptionToThrowToClient(t); } - } + } + + @Override + public void undeployStorageNode(StorageNode storageNode) throws RuntimeException { + try { + storageNodeManager.undeployStorageNode(getSessionSubject(), storageNode); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override + public void deployStorageNode(StorageNode storageNode) throws RuntimeException { + try { + storageNodeManager.deployStorageNode(getSessionSubject(), storageNode); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } }
commit da1bc7863207dde3ae2cc51811b3cbfae26761b4 Author: Lukas Krejci lkrejci@redhat.com Date: Mon Aug 19 17:52:53 2013 +0200
[BZ 986491] - Yum content source plugin now handles HTTP basic auth
It also should be able to handle HTTPS and other URL schemes if support for them is available in the RHQ server's JVM.
diff --git a/modules/enterprise/server/plugins/yum/pom.xml b/modules/enterprise/server/plugins/yum/pom.xml index e52c04b..bef9d81 100644 --- a/modules/enterprise/server/plugins/yum/pom.xml +++ b/modules/enterprise/server/plugins/yum/pom.xml @@ -32,6 +32,20 @@ <scope>provided</scope> <!-- this version of jdom is included in the server, we'll juse reuse it --> </dependency>
+ <!-- Test deps --> + <dependency> + <groupId>org.rhq</groupId> + <artifactId>test-utils</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.jboss.resteasy</groupId> + <artifactId>tjws</artifactId> + <version>3.0.3.Final</version> + <scope>test</scope> + </dependency> </dependencies>
<build> @@ -128,4 +142,4 @@ </profile> </profiles>
-</project> \ No newline at end of file +</project> diff --git a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/DiskReader.java b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/DiskReader.java index f131471..6a2227f 100644 --- a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/DiskReader.java +++ b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/DiskReader.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2008 Red Hat, Inc. + * Copyright (C) 2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -16,13 +16,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + package org.rhq.enterprise.server.plugins.yum;
import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; -import java.util.zip.GZIPInputStream; +import java.net.URISyntaxException; +import java.net.URL;
/** * The disk reader is a yum repo reader used to read metadata and bits from an existing yum repo that is located on a @@ -30,56 +30,24 @@ import java.util.zip.GZIPInputStream; * * @author jortel */ -public class DiskReader implements RepoReader { - /** - * The base or root directory path of a yum repo. - */ - private final String basepath; +public class DiskReader extends UrlReader {
- /** - * Constructor. - * - * @param basepath The base or root directory path of a yum repo. - */ - public DiskReader(String basepath) { - this.basepath = basepath; + public DiskReader(URL baseUrl) { + super(baseUrl); }
/** * Validate the reader. Validates that the base path is an existing directory that is readable. * - * @throws Exception When <i>basepath</i> is not a directory, does not exist, or is not readable. + * @throws IOException When <i>baseUrl</i> is not a directory, does not exist, or is not readable. */ - public void validate() throws Exception { - File file = new File(basepath); - if (file.exists() || file.canRead() || file.isDirectory()) { + @Override + public void validate() throws IOException, URISyntaxException { + File file = new File(baseUrl.toURI().getSchemeSpecificPart()); + if (file.exists() && file.canRead() && file.isDirectory()) { return; // good }
- throw new Exception("Path: '" + basepath + "' not found, not a directory or permission denied"); - } - - /** - * Open an input stream to specifed relative path. Prepends the basepath to the <i>path</i> and opens and opens and - * input stream. - * - * @param path A relative path to a file within the repo. - * - * @return An open input stream that <b>must</b> be closed by the caller. - * - * @throws IOException On all errors. - */ - public InputStream openStream(String path) throws IOException { - InputStream in = new FileInputStream(basepath + "/" + path); - if (path.endsWith(".gz")) { - return new GZIPInputStream(in); - } - - return in; - } - - @Override - public String toString() { - return "basepath: " + basepath; + throw new IOException("Path: '" + baseUrl + "' not found, not a directory or permission denied"); } -} \ No newline at end of file +} diff --git a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/HttpReader.java b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/HttpReader.java index 98e115c..99eecdd 100644 --- a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/HttpReader.java +++ b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/HttpReader.java @@ -21,80 +21,58 @@ package org.rhq.enterprise.server.plugins.yum; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import java.net.URISyntaxException; import java.net.URL; import java.util.zip.GZIPInputStream;
+import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.rhq.core.util.Base64; + /** * The http reader is a yum repo reader used to read metadata and bits from an existing (remote) yum repo using yum's * native http interface. * * @author jortel */ -public class HttpReader implements RepoReader { - /** - * The base url of a yum repo. - */ - private final String baseurl; +public class HttpReader extends UrlReader {
- /** - * The current url connection - */ - HttpURLConnection connection; + private static final Log LOG = LogFactory.getLog(RepoProvider.class); + + private final String username; + private final String password;
/** * Constructor. * - * @param basepath The base url of a yum repo. + * @param baseUrl The base url of a yum repo. + * @param username the name of the user to authenticate with or null + * @param password the password to use or null */ - public HttpReader(String baseurl) { - this.baseurl = baseurl; + public HttpReader(URL baseUrl, String username, String password) { + super(baseUrl); + this.username = username; + this.password = password; }
- /** - * Validate the reader. Validates that the base url is valid. - * - * @throws Exception When <i>baseurl</i> is not valid. - */ - public void validate() throws Exception { - URL url = new URL(baseurl); - connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - try { - if (connection.getHeaderField(0) == null) { - throw new IOException("Cannot validate connection - check URL"); - } - } finally { - connection.disconnect(); - } - } - - /** - * Open an input stream to specifed relative url. Prepends the baseurl to the <i>url</i> and opens and opens and - * input stream. Files with a .gz suffix will be unziped (inline). - * - * @param suffix A url that is relative to the <i>baseurl</i> and references a file within the repo. - * - * @return An open input stream that <b>must</b> be closed by the caller. - * - * @throws IOException On all errors. - */ - public InputStream openStream(String suffix) throws IOException { - URL url = new URL(baseurl + "/" + suffix); - connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - InputStream in = connection.getInputStream(); - if (suffix.endsWith(".gz")) { - return new GZIPInputStream(in); + @Override + protected InputStream doOpen(URL url) throws IOException { + if (LOG.isDebugEnabled()) { + LOG.debug("open " + url); }
- return in; - } + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setInstanceFollowRedirects(true);
- /* - * (non-Javadoc) @see java.lang.Object#toString() - */ - @Override - public String toString() { - return baseurl; + if (username != null) { + String userInfo = username; + if (password != null) { + userInfo += ":" + password; + } + String basicAuth = "Basic " + Base64.encode(userInfo.getBytes("ISO-8859-1")); + connection.setRequestProperty("Authorization", basicAuth); + } + return connection.getInputStream(); } -} \ No newline at end of file +} diff --git a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java index f065ba7..2e04453 100644 --- a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java +++ b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java @@ -19,6 +19,9 @@ package org.rhq.enterprise.server.plugins.yum;
import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -84,20 +87,19 @@ public class RepoProvider implements ContentProvider, PackageSource { throw new IllegalArgumentException("Missing required 'location' property"); }
- location = trim(location); - log.info("Initialized with location: " + location); - if (location.startsWith("http://")) { - reader = new HttpReader(location); - return; - } + location = location.trim(); + String username = configuration.getSimpleValue("username"); + String password = configuration.getSimpleValue("password");
- if (location.startsWith("file://")) { - location = location.substring(7); - reader = new DiskReader(location); - return; - } + URI uri = new URI(location);
- reader = new DiskReader(location); + log.info("Initialized with location: " + location); + try { + reader = UrlReader.fromUri(uri, username, password); + } catch (MalformedURLException e) { + log.error("Could not determine a reader for the URI [" + uri + "]"); + throw e; + } }
/** @@ -176,22 +178,6 @@ public class RepoProvider implements ContentProvider, PackageSource { reader.validate(); }
- /** - * Trim white space and trailing (/) characters. - * - * @param path A url/directory path string. - * - * @return A trimmed string. - */ - private String trim(String path) { - path = path.trim(); - while ((path.length() > 1) && path.endsWith("/")) { - path = path.substring(0, path.length() - 1); - } - - return path; - } - public SyncProgressWeight getSyncProgressWeight() { return SyncProgressWeight.DEFAULT_WEIGHTS; } diff --git a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/UrlReader.java b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/UrlReader.java new file mode 100644 index 0000000..682b319 --- /dev/null +++ b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/UrlReader.java @@ -0,0 +1,111 @@ +/* + * RHQ Management Platform + * Copyright (C) 2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.server.plugins.yum; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.util.zip.GZIPInputStream; + +/** + * @author Lukas Krejci + * @since 4.9 + */ +public class UrlReader implements RepoReader { + + protected final URL baseUrl; + + public static UrlReader fromUri(URI uri, String username, String password) throws MalformedURLException { + if (uri.getScheme() == null) { + try { + return new DiskReader(new URI("file", uri.getSchemeSpecificPart(), uri.getFragment()).toURL()); + } catch (URISyntaxException e) { + throw new IllegalStateException( + "URI syntax exception while adding the 'file' scheme to a path. This should not have happened.", e); + } + } else if (uri.getScheme().equals("file")) { + return new DiskReader(uri.toURL()); + } else if (uri.getScheme().startsWith("http")) { + return new HttpReader(uri.toURL(), username, password); + } else { + return new UrlReader(uri.toURL()); + } + } + + protected UrlReader(URL baseUrl) { + this.baseUrl = baseUrl; + + } + + public void validate() throws IOException, URISyntaxException { + InputStream content = doOpen(baseUrl); + content.close(); + } + + /** + * Open an input stream to specifed relative url. Prepends the baseurl to the <i>url</i> and opens and opens and + * input stream. Files with a .gz suffix will be unziped (inline). + * + * @param path A path that is relative to the <i>baseurl</i> and references a file within the repo. + * + * @return An open input stream that <b>must</b> be closed by the caller. + * + * @throws IOException On all errors. + */ + @Override + public final InputStream openStream(String path) throws IOException { + URL url = extendBaseUrl(path); + + InputStream ret = doOpen(url); + if (path.endsWith(".gz")) { + ret = new GZIPInputStream(ret); + } + + return ret; + } + + protected InputStream doOpen(URL url) throws IOException { + return url.openStream(); + } + + /** + * Mainly used for test purposes, othewise not really useful. + */ + public URL getBaseURL() { + return baseUrl; + } + + protected URL extendBaseUrl(String suffix) throws MalformedURLException { + if (suffix != null) { + suffix = suffix.trim(); + } + + return suffix == null ? baseUrl : new URL(baseUrl + "/" + suffix); + } + + @Override + public String toString() { + return getClass().getSimpleName() + " " + baseUrl; + } +} diff --git a/modules/enterprise/server/plugins/yum/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/yum/src/main/resources/META-INF/rhq-serverplugin.xml index b501235..2ced81c 100644 --- a/modules/enterprise/server/plugins/yum/src/main/resources/META-INF/rhq-serverplugin.xml +++ b/modules/enterprise/server/plugins/yum/src/main/resources/META-INF/rhq-serverplugin.xml @@ -24,7 +24,11 @@ type="string" required="true" description="The URL or path to the Yum repository" /> + <c:simple-property name="username" type="string" required="false" + description="The optional user name to authenticate with"/> + <c:simple-property name="password" type="password" required="false" + description="The optional password to authenticate with"/> </configuration> </contentSourceType>
-</content-plugin> \ No newline at end of file +</content-plugin> diff --git a/modules/enterprise/server/plugins/yum/src/test/java/Acme/Serve/UrlReaderTestServer.java b/modules/enterprise/server/plugins/yum/src/test/java/Acme/Serve/UrlReaderTestServer.java new file mode 100644 index 0000000..43f3d33 --- /dev/null +++ b/modules/enterprise/server/plugins/yum/src/test/java/Acme/Serve/UrlReaderTestServer.java @@ -0,0 +1,64 @@ +/* + * RHQ Management Platform + * Copyright (C) 2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package Acme.Serve; + +import java.io.PrintStream; +import java.util.Map; +import java.util.Properties; + +/** + * This needs to be in the {@code Acme.Serve} package so that authentication realm can be defined. + * + * @author Lukas Krejci + * @since 4.9 + */ +public class UrlReaderTestServer extends Serve { + private static final long serialVersionUID = 1L; + + + public static class AuthRealm extends BasicAuthRealm { + + private static final long serialVersionUID = 1L; + + public AuthRealm(String name) { + super(name); + } + } + + public UrlReaderTestServer(Map arguments, PrintStream logStream) { + super(arguments, logStream); + } + + @Override + public void setMappingTable(PathTreeDictionary mappingTable) { + super.setMappingTable(mappingTable); + } + + @Override + protected void initMime() { + mime = new Properties(); + mime.put("file", "text/plain"); + } + + @Override + public void setRealms(PathTreeDictionary realms) { + super.setRealms(realms); + } +} diff --git a/modules/enterprise/server/plugins/yum/src/test/java/org/rhq/enterprise/server/plugins/yum/UrlReaderTest.java b/modules/enterprise/server/plugins/yum/src/test/java/org/rhq/enterprise/server/plugins/yum/UrlReaderTest.java new file mode 100644 index 0000000..62e9c18 --- /dev/null +++ b/modules/enterprise/server/plugins/yum/src/test/java/org/rhq/enterprise/server/plugins/yum/UrlReaderTest.java @@ -0,0 +1,195 @@ +package org.rhq.enterprise.server.plugins.yum;/* + * RHQ Management Platform + * Copyright (C) 2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +import static org.testng.Assert.assertEquals; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import org.rhq.core.util.stream.StreamUtil; +import org.rhq.test.PortScout; + +import Acme.Serve.Serve; +import Acme.Serve.UrlReaderTestServer; + +/** + * @author Lukas Krejci + * @since 4.9 + */ +@Test +public class UrlReaderTest { + + private static final String TEST_USER = "testUser"; + private static final String TEST_PASSWORD = "password"; + + private static class AuthServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String authType = req.getAuthType(); + String remoteUser = req.getRemoteUser(); + + assertEquals(authType, "BASIC", "Unexpected authentication type"); + assertEquals(remoteUser, TEST_USER, "Unexpected authenticated user."); + + String path = req.getPathTranslated(); + if (path != null) { + FileInputStream in = new FileInputStream(path); + try { + StreamUtil.copy(in, resp.getOutputStream(), false); + } finally { + in.close(); + } + } + } + } + + private UrlReaderTestServer httpServer; + private String rootUrl; + + @BeforeClass + public void startWebServer() throws IOException, URISyntaxException { + PortScout portScout = new PortScout(); + int httpPort = portScout.getNextFreePort(); + + Map<String, Object> params = new HashMap<String, Object>(); + params.put(Serve.ARG_PORT, httpPort); + params.put(Serve.ARG_NOHUP, "nohup"); + + httpServer = new UrlReaderTestServer(params, System.err); + + Serve.PathTreeDictionary aliases = new Serve.PathTreeDictionary(); + File root = getRoot(); + aliases.put("/", root); + aliases.put("/*", root); + + httpServer.setMappingTable(aliases); + httpServer.addDefaultServlets(null); + + httpServer.addServlet("/auth", new AuthServlet()); + + UrlReaderTestServer.AuthRealm authRealm = new UrlReaderTestServer.AuthRealm("auth"); + authRealm.put(TEST_USER, TEST_PASSWORD); + + Serve.PathTreeDictionary realms = new Serve.PathTreeDictionary(); + realms.put("/auth", authRealm); + + httpServer.setRealms(realms); + portScout.close(); + + httpServer.runInBackground(); + + rootUrl = InetAddress.getLocalHost().getHostAddress() + ":" + httpPort; + } + + @AfterClass(alwaysRun = true) + public void stopWebServer() throws IOException { + httpServer.stopBackground(); + httpServer.destroyAllServlets(); + } + + public void picksCorrectImpl() throws Exception { + URI httpUrl = new URI("http://jboss.org/rhq"); + URI httpsUrl = new URI("https://jboss.org/rhq"); + URI noSchemeUrl = new URI("stairway/to/heaven"); + URI fileUrl = new URI("file:/over/the/rainbow"); + + UrlReader httpRdr = UrlReader.fromUri(httpUrl, null, null); + UrlReader httpsRdr = UrlReader.fromUri(httpsUrl, null, null); + UrlReader noSchemeRdr = UrlReader.fromUri(noSchemeUrl, null, null); + UrlReader fileRdr = UrlReader.fromUri(fileUrl, null, null); + + assertReader(httpRdr, httpUrl.toURL(), HttpReader.class); + assertReader(httpsRdr, httpsUrl.toURL(), HttpReader.class); + assertReader(noSchemeRdr, new URL("file:stairway/to/heaven"), DiskReader.class); + assertReader(fileRdr, fileUrl.toURL(), DiskReader.class); + } + + public void readsFiles() throws Exception { + UrlReader fileReader = UrlReader.fromUri(getRoot().toURI(), null, null); + + testReaderWithTestFile(fileReader); + } + + public void readsHttp() throws Exception { + URI uri = new URI("http://" + rootUrl); + + UrlReader httpReader = UrlReader.fromUri(uri, null, null); + + testReaderWithTestFile(httpReader); + } + + public void authenticatesInHttp() throws Exception { + URI uri = new URI("http://" + rootUrl + "/auth"); + + UrlReader httpReader = UrlReader.fromUri(uri, TEST_USER, TEST_PASSWORD); + + testReaderWithTestFile(httpReader); + } + + private static void assertReader(UrlReader instance, URL expectedUrl, Class<? extends UrlReader> expectedType) { + assertEquals(instance.getClass(), expectedType, "Unexpected reader type"); + assertEquals(instance.getBaseURL(), expectedUrl, "Unexpected baseUrl"); + } + + private void testReaderWithTestFile(UrlReader reader) throws IOException, URISyntaxException { + try { + reader.validate(); + } catch (IOException e) { + Assert.fail("Validation of " + reader.getClass().getSimpleName() + " reader failed", e); + } + + Reader rdr = new InputStreamReader(reader.openStream("test.file")); + try { + String contents = StreamUtil.slurp(rdr); + + assertEquals(contents, "kachny\n", "Unexpected contents of the test file"); + } finally { + rdr.close(); + } + } + + private File getRoot() throws URISyntaxException { + URI testUri = getClass().getResource("/test.file").toURI(); + + File testFile = new File(testUri.getSchemeSpecificPart()); + return testFile.getParentFile(); + } +} diff --git a/modules/enterprise/server/plugins/yum/src/test/resources/test.file b/modules/enterprise/server/plugins/yum/src/test/resources/test.file new file mode 100644 index 0000000..8742087 --- /dev/null +++ b/modules/enterprise/server/plugins/yum/src/test/resources/test.file @@ -0,0 +1 @@ +kachny
commit cece52f8f9a1c44269ae6e76ad73b0251da09cfe Author: Jirka Kremser jkremser@redhat.com Date: Mon Aug 19 14:38:10 2013 +0200
Fixing/handling errors in UI when storage node has no associated resource id (this can happen when installing everything with "rhqctl install --agent-auto-start false").
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java index d6a91cb..d1ea625 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java @@ -122,15 +122,17 @@ public class StorageNodeAdminView extends EnhancedVLayout implements Bookmarkabl GWTServiceLookup.getStorageService().findResourcesWithAlertDefinitions(new AsyncCallback<Integer[]>() { @Override public void onFailure(Throwable caught) { - Message message = new Message("foobar", - Message.Severity.Warning); + Message message = new Message("Unable to render storage node alert view: " + + caught.getMessage(), Message.Severity.Warning); CoreGUI.goToView(VIEW_ID.getName(), message); }
@Override public void onSuccess(Integer[] result) { if (result == null || result.length == 0) { - onFailure(new Exception("foobaz")); + onFailure(new Exception( + "Unfortunately, there are no associated resources for the available storage nodes. " + + "Check if the agents are running on the machines where the storage nodes are deployed.")); } else { resIds = ArrayUtils.unwrapArray(result); tabset.getTabByName(tabInfo.name.getName()).setPane( diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java index a89bb81..685fb5d 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java @@ -250,7 +250,8 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit } int value = from.getUnackAlerts(); record.setAttribute(FIELD_ALERTS.propertyName(), - StorageNodeAdminView.getAlertsString("New Alerts", node.getId(), value)); + node.getResource() != null ? StorageNodeAdminView.getAlertsString("New Alerts", node.getId(), value) + : "New Alerts (0)"); String memory = null; if (from.getHeapPercentageUsed() != null && from.getHeapPercentageUsed().getAggregate().getAvg() != null) memory = MeasurementConverterClient.format(from.getHeapPercentageUsed().getAggregate().getAvg(), from diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java index 6fdae0c..4055e6f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java @@ -23,7 +23,6 @@ import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDat import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_ALERTS; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_CQL_PORT; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_CTIME; -import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_FAILED_OPERATION; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_JMX_PORT; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_MTIME; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_OPERATION_MODE; @@ -67,7 +66,6 @@ import org.rhq.enterprise.gui.coregui.client.util.Log; import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout; -import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedUtility; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -130,9 +128,11 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab final StorageNode node = storageNodes.get(0); header.setContents("<div style='text-align: center; font-weight: bold; font-size: medium;'> Storage Node (" + node.getAddress() + ")</div>"); - fetchStorageNodeConfigurationComposite(node); + prepareDetailsSection(node); + fetchStorageNodeConfigurationComposite(node); fetchSparkLineDataForLoadComponent(node); + fetchUnackAlerts(storageNodeId, node.getResource() != null); }
public void onFailure(Throwable caught) { @@ -142,45 +142,76 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab initSectionCount = SECTION_COUNT; } }); - fetchUnackAlerts(storageNodeId); }
private void fetchStorageNodeConfigurationComposite(final StorageNode node) { - GWTServiceLookup.getStorageService().retrieveConfiguration(node, - new AsyncCallback<StorageNodeConfigurationComposite>() { - @Override - public void onFailure(Throwable caught) { - Message message = new Message(MSG.view_configurationHistoryDetails_error_loadFailure(), - Message.Severity.Warning); - initSectionCount = SECTION_COUNT; - } + if (node.getResource() == null) { // no associated resource yet + LayoutSpacer spacer = new LayoutSpacer(); + spacer.setHeight(15); + HTMLFlow info = new HTMLFlow("<h2>There is no configuration available for this node. Is the agent running on the " + + node.getAddress() + "?</h2>"); + SectionStackSection section = new SectionStackSection("Configuration"); + section.setItems(spacer, info); + section.setExpanded(true); + section.setCanCollapse(false); + + configurationSection = section; + initSectionCount++; + } else { + GWTServiceLookup.getStorageService().retrieveConfiguration(node, + new AsyncCallback<StorageNodeConfigurationComposite>() { + @Override + public void onFailure(Throwable caught) { + Message message = new Message(MSG.view_configurationHistoryDetails_error_loadFailure(), + Message.Severity.Warning); + initSectionCount = SECTION_COUNT; + }
- @Override - public void onSuccess(StorageNodeConfigurationComposite result) { - prepareResourceConfigEditor(result); - } - }); + @Override + public void onSuccess(StorageNodeConfigurationComposite result) { + prepareResourceConfigEditor(result); + } + }); + } }
private void fetchSparkLineDataForLoadComponent(final StorageNode storageNode) { + if (storageNode.getResource() == null) { + HTMLFlow info = new HTMLFlow("<i>No load data available.</i>"); + info.setExtraSpace(5); + loadLayout = new EnhancedVLayout(); + loadLayout.setWidth100(); + LayoutSpacer spacer = new LayoutSpacer(); + spacer.setHeight(10); + HTMLFlow loadLabel = new HTMLFlow("Status"); + loadLabel.addStyleName("formTitle"); + loadLabel.setHoverWidth(300); + loadLayout.setMembers(spacer, loadLabel, info); + + if (detailsAndLoadLayout == null) { + detailsAndLoadLayout = new EnhancedHLayout(); + } + initSectionCount++; + } else { + GWTServiceLookup.getStorageService().findStorageNodeLoadDataForLast(storageNode, 8, + MeasurementUtility.UNIT_HOURS, 60, + new AsyncCallback<Map<String, List<MeasurementDataNumericHighLowComposite>>>() { + @Override + public void onFailure(Throwable caught) {
- GWTServiceLookup.getStorageService().findStorageNodeLoadDataForLast(storageNode, 8, MeasurementUtility.UNIT_HOURS, - 60, new AsyncCallback<Map<String, List<MeasurementDataNumericHighLowComposite>>>() { - @Override - public void onFailure(Throwable caught) { - - } + }
- @Override - public void onSuccess(Map<String, List<MeasurementDataNumericHighLowComposite>> result) { - prepareLoadSection(sectionStack, storageNode, result); - } + @Override + public void onSuccess(Map<String, List<MeasurementDataNumericHighLowComposite>> result) { + prepareLoadSection(sectionStack, storageNode, result); + }
- }); + }); + } }
- private void fetchUnackAlerts(final int storageNodeId) { + private void fetchUnackAlerts(final int storageNodeId, final boolean isResourceIdSet) { GWTServiceLookup.getStorageService().findNotAcknowledgedStorageNodeAlertsCounts(Arrays.asList(storageNodeId), new AsyncCallback<List<Integer>>() { @Override @@ -198,7 +229,7 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab } else { unackAlerts = result.get(0); if (alertsItem != null) { - alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, unackAlerts)); + alertsItem.setValue(isResourceIdSet ? StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, unackAlerts) : "New Alerts (0)"); } } } @@ -263,15 +294,16 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab
final StaticTextItem cqlPortItem = new StaticTextItem(FIELD_CQL_PORT.propertyName(), FIELD_CQL_PORT.title()); cqlPortItem.setValue(storageNode.getCqlPort()); - + final StaticTextItem jmxPortItem = new StaticTextItem(FIELD_JMX_PORT.propertyName(), FIELD_JMX_PORT.title()); jmxPortItem.setValue(storageNode.getJmxPort());
-// final StaticTextItem jmxConnectionUrlItem = new StaticTextItem("jmxConnectionUrl", -// MSG.view_adminTopology_storageNode_jmxConnectionUrl()); -// jmxConnectionUrlItem.setValue(storageNode.getJMXConnectionURL()); + // final StaticTextItem jmxConnectionUrlItem = new StaticTextItem("jmxConnectionUrl", + // MSG.view_adminTopology_storageNode_jmxConnectionUrl()); + // jmxConnectionUrlItem.setValue(storageNode.getJMXConnectionURL());
- final StaticTextItem operationModeItem = new StaticTextItem(FIELD_OPERATION_MODE.propertyName(), MSG.view_adminTopology_serverDetail_operationMode()); + final StaticTextItem operationModeItem = new StaticTextItem(FIELD_OPERATION_MODE.propertyName(), + MSG.view_adminTopology_serverDetail_operationMode()); operationModeItem.setValue(storageNode.getOperationMode());
// make clickable link to associated resource @@ -294,35 +326,52 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab StaticTextItem lastUpdateItem = new StaticTextItem(FIELD_MTIME.propertyName(), FIELD_MTIME.title()); lastUpdateItem.setValue(TimestampCellFormatter.format(Long.valueOf(storageNode.getMtime()), TimestampCellFormatter.DATE_TIME_FORMAT_LONG)); - + alertsItem = new StaticTextItem(FIELD_ALERTS.propertyName(), FIELD_ALERTS.title()); - alertsItem.setPrompt("The number in brackets represents the number of unacknowledged alerts for this storage node."); + alertsItem + .setPrompt("The number in brackets represents the number of unacknowledged alerts for this storage node."); if (unackAlerts != -1) { alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, unackAlerts)); } - - StaticTextItem message = new StaticTextItem("message", "Note"); - message.setValue(storageNode.getErrorMessage() == null ? "Everything is ok" : storageNode.getErrorMessage()); - + + StaticTextItem messageItem = new StaticTextItem("message", "Note"); + StringBuffer message = new StringBuffer(); + boolean isOk = true; + if (storageNode.getResource() == null) { + message.append("Storage node has no associated resource.<br />"); + isOk = false; + } + if (storageNode.getErrorMessage() != null) { + message.append(storageNode.getErrorMessage()).append("<br />"); + isOk = false; + } + if (isOk) { + message.append("Everything is ok"); + } + messageItem.setValue(message); + StaticTextItem lastOperation = null; - boolean isOperationFailed = storageNode.getFailedOperation() != null && storageNode.getFailedOperation().getResource() != null; + boolean isOperationFailed = storageNode.getFailedOperation() != null + && storageNode.getFailedOperation().getResource() != null; if (isOperationFailed) { ResourceOperationHistory operationHistory = storageNode.getFailedOperation(); - String value = LinkManager.getSubsystemResourceOperationHistoryLink(operationHistory.getResource().getId(), operationHistory.getId()); -// String value = "#Resource/" + operationHistory.getResource().getId() + "/Operations/History/" + operationHistory.getId()); + String value = LinkManager.getSubsystemResourceOperationHistoryLink(operationHistory.getResource().getId(), + operationHistory.getId()); + // String value = "#Resource/" + operationHistory.getResource().getId() + "/Operations/History/" + operationHistory.getId()); lastOperation = new StaticTextItem("lastOp", "Operation"); - lastOperation.setValue(LinkManager.getHref(value, operationHistory.getOperationDefinition().getDisplayName())); + lastOperation.setValue(LinkManager.getHref(value, operationHistory.getOperationDefinition() + .getDisplayName())); } - - - + List<FormItem> formItems = new ArrayList<FormItem>(6); - formItems.addAll(Arrays.asList(nameItem, resourceItem,cqlPortItem, jmxPortItem/*, jmxConnectionUrlItem*/)); - if (!CoreGUI.isDebugMode()) formItems.add(operationModeItem); // debug mode fails if this item is added - formItems.addAll(Arrays.asList(installationDateItem, lastUpdateItem, alertsItem, message)); - if (isOperationFailed) formItems.add(lastOperation); - form.setItems(formItems.toArray(new FormItem[]{})); - + formItems.addAll(Arrays.asList(nameItem, resourceItem, cqlPortItem, jmxPortItem/*, jmxConnectionUrlItem*/)); + if (!CoreGUI.isDebugMode()) + formItems.add(operationModeItem); // debug mode fails if this item is added + formItems.addAll(Arrays.asList(installationDateItem, lastUpdateItem, alertsItem, messageItem)); + if (isOperationFailed) + formItems.add(lastOperation); + form.setItems(formItems.toArray(new FormItem[] {})); + detailsLayout = new EnhancedVLayout(); detailsLayout.setWidth(450); detailsLayout.addMember(form); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java index efe56e3..84c1586 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java @@ -27,7 +27,7 @@ import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.rhq.enterprise.gui.coregui.client.util.Log; + import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Criteria; @@ -50,6 +50,7 @@ import org.rhq.enterprise.gui.coregui.client.components.table.AuthorizedTableAct import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement; import org.rhq.enterprise.gui.coregui.client.components.table.TableSection; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.util.Log; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; import org.rhq.enterprise.gui.coregui.client.util.async.Command; import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch; @@ -83,6 +84,7 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { @Override protected void doOnDraw() { super.doOnDraw(); + // commenting out this call, because it caused UI to freeze // scheduleUnacknowledgedAlertsPollingJob(getListGrid()); }
@@ -178,6 +180,11 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { ListGrid listGrid = new ListGrid() { @Override protected Canvas getExpansionComponent(final ListGridRecord record) { + if (record.getAttribute(FIELD_RESOURCE_ID.propertyName()) == null) { + // no resource set + return new HTMLFlow("There is no load data available for this node. Is the agent running on the " + + record.getAttributeAsString(FIELD_ADDRESS.propertyName() + "?")); + } int id = record.getAttributeAsInt(FIELD_ID); return new StorageNodeLoadComponent(id, null); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 04abeb88..55593d3 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -469,10 +469,15 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN long endTime = System.currentTimeMillis(); long beginTime = endTime - (8 * 60 * 60 * 1000); for (StorageNode node : nodes) { - StorageNodeLoadComposite composite = getLoad(subjectManager.getOverlord(), node, beginTime, endTime); - int unackAlerts = findNotAcknowledgedStorageNodeAlerts(subjectManager.getOverlord(), node).size(); - composite.setUnackAlerts(unackAlerts); - result.add(composite); + if (node.getOperationMode() != OperationMode.INSTALLED) { + StorageNodeLoadComposite composite = getLoad(subjectManager.getOverlord(), node, beginTime, endTime); + int unackAlerts = findNotAcknowledgedStorageNodeAlerts(subjectManager.getOverlord(), node).size(); + composite.setUnackAlerts(unackAlerts); + result.add(composite); + } else { // newly installed node + result.add(new StorageNodeLoadComposite(node, beginTime, endTime)); + } + } return result; }
commit 144e622efb8ec61816b4716f6f696e2330e3f4e9 Author: Stefan Negrea snegrea@redhat.com Date: Sat Aug 17 19:25:18 2013 -0500
[BZ 993513] Baselines entries are no longer calculated and inserted into the SQL database if there is no data in the storage.
The sql query that returns the schedules that need recomputation has been updated to return only the ids of the schedules, reducing the amount of data requested from SQL to the minimum.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementBaseline.java b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementBaseline.java index 5bd0e8b..681914d 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementBaseline.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/measurement/MeasurementBaseline.java @@ -94,6 +94,8 @@ public class MeasurementBaseline implements Serializable { @OneToOne(fetch = FetchType.LAZY, optional = false) private MeasurementSchedule schedule;
+ @Column(name = "SCHEDULE_ID", insertable = false, updatable = false) + private int scheduleId;
public MeasurementBaseline() { computeTime = System.currentTimeMillis(); @@ -176,6 +178,20 @@ public class MeasurementBaseline implements Serializable { }
/** + * @return the scheduleId + */ + public int getScheduleId() { + return scheduleId; + } + + /** + * @param scheduleId the scheduleId to set + */ + public void setScheduleId(int scheduleId) { + this.scheduleId = scheduleId; + } + + /** * If <code>true</code>, it means a user manually entered the baseline values, as opposed to having them * automatically be calculated by examining past measurement data. * diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java index 90ac6e7..ed8db3a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerBean.java @@ -18,10 +18,9 @@ */ package org.rhq.enterprise.server.measurement;
+import java.util.ArrayList; import java.util.Arrays; import java.util.Date; -import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Properties;
@@ -48,10 +47,10 @@ import org.rhq.enterprise.server.RHQConstants; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.authz.AuthorizationManagerLocal; import org.rhq.enterprise.server.authz.PermissionException; -import org.rhq.enterprise.server.storage.StorageClientManagerBean; import org.rhq.enterprise.server.cloud.StatusManagerLocal; import org.rhq.enterprise.server.measurement.instrumentation.MeasurementMonitor; import org.rhq.enterprise.server.resource.ResourceManagerLocal; +import org.rhq.enterprise.server.storage.StorageClientManagerBean; import org.rhq.enterprise.server.system.SystemManagerLocal; import org.rhq.server.metrics.MetricsBaselineCalculator;
@@ -148,8 +147,6 @@ public class MeasurementBaselineManagerBean implements MeasurementBaselineManage + (System.currentTimeMillis() - now) + ")ms");
now = System.currentTimeMillis(); - int totalProcessed = 0; - while (true) { /* * each call is done in a separate xtn of at most 100K inserted rows; this helps to keep the xtn * shorter to avoid timeouts in scenarios where baseline calculations bunch together. the idea was that @@ -189,16 +186,22 @@ public class MeasurementBaselineManagerBean implements MeasurementBaselineManage * In any event, an appropriate chunking solution needs to be found, and that partitioning strategy * needs to replace the limits in the query today. */ - List<MeasurementSchedule> schedulesWithoutBaselines = - measurementBaselineManager.getSchedulesWithoutBaselines(); - measurementBaselineManager.calculateBaselines(schedulesWithoutBaselines, now, amountOfData); - totalProcessed += schedulesWithoutBaselines.size(); - - if (schedulesWithoutBaselines.size() < BASELINE_PROCESSING_LIMIT) { - break; + List<Integer> schedulesWithoutBaselines = measurementBaselineManager.getSchedulesWithoutBaselines(); + + List<Integer> accumulator = new ArrayList<Integer>(); + for (Integer value : schedulesWithoutBaselines) { + accumulator.add(value); + if (accumulator.size() == BASELINE_PROCESSING_LIMIT) { + measurementBaselineManager.calculateBaselines(accumulator, now, amountOfData); + accumulator.clear(); } } - log.info("Calculated and inserted [" + totalProcessed + "] new baselines. (" + if (!accumulator.isEmpty()) { + measurementBaselineManager.calculateBaselines(accumulator, now, amountOfData); + accumulator.clear(); + } + + log.info("Calculated and inserted [" + schedulesWithoutBaselines.size() + "] new baselines. (" + (System.currentTimeMillis() - now) + ")ms");
MeasurementMonitor.getMBean().incrementBaselineCalculationTime(System.currentTimeMillis() - computeTime); @@ -222,18 +225,17 @@ public class MeasurementBaselineManagerBean implements MeasurementBaselineManage
@SuppressWarnings("unchecked") @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - public List<MeasurementSchedule> getSchedulesWithoutBaselines() { - String sql = - "SELECT s.* FROM rhq_measurement_sched s INNER JOIN rhq_measurement_def d ON s.definition = d.id " + - "LEFT JOIN rhq_measurement_bline b ON s.id = b.schedule_id WHERE b.schedule_id IS NULL AND d.numeric_type = 0"; - Query query = this.entityManager.createNativeQuery(sql, MeasurementSchedule.class); - query.setMaxResults(BASELINE_PROCESSING_LIMIT); + public List<Integer> getSchedulesWithoutBaselines() { + final String sql = + "SELECT s.id FROM rhq_measurement_sched s INNER JOIN rhq_measurement_def d ON s.definition = d.id " + + "LEFT JOIN rhq_measurement_bline b ON s.id = b.schedule_id WHERE s.enabled = true AND b.schedule_id IS NULL AND d.numeric_type = 0"; + Query query = this.entityManager.createNativeQuery(sql);
return query.getResultList(); }
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) - public void calculateBaselines(List<MeasurementSchedule> schedules, long olderThan, long amountOfData) { + public void calculateBaselines(List<Integer> schedules, long olderThan, long amountOfData) { long endTime = olderThan; long startTime = endTime - amountOfData;
@@ -242,30 +244,21 @@ public class MeasurementBaselineManagerBean implements MeasurementBaselineManage long calcStartTime = System.currentTimeMillis(); List<MeasurementBaseline> results = baselineCalculator.calculateBaselines(schedules, startTime, endTime); long calcEndTime = System.currentTimeMillis(); - int count = results.size();
if (log.isDebugEnabled()) { - log.debug("Finished computing " + count + " new baselines in " + (calcEndTime - calcStartTime) + " ms"); + log.debug("Finished computing " + results.size() + " new baselines in " + (calcEndTime - calcStartTime) + + " ms"); }
log.debug("Persisting baselines calculations"); long saveStartTime = System.currentTimeMillis(); - Iterator<MeasurementBaseline> iterator = results.iterator(); - List<MeasurementBaseline> queue = new LinkedList<MeasurementBaseline>(); - while (iterator.hasNext()) { - if (queue.size() == 10) { - measurementBaselineManager.saveNewBaselines(queue); - queue = new LinkedList<MeasurementBaseline>(); - } - queue.add(iterator.next()); - } - if (!queue.isEmpty()) { - measurementBaselineManager.saveNewBaselines(queue); - } + + measurementBaselineManager.saveNewBaselines(results);
long saveEndTime = System.currentTimeMillis(); if (log.isDebugEnabled()) { - log.debug("Finished persisting " + count + " baselines in " + (saveEndTime - saveStartTime) + " ms"); + log.debug("Finished persisting " + results.size() + " baselines in " + (saveEndTime - saveStartTime) + + " ms"); } }
@@ -273,7 +266,10 @@ public class MeasurementBaselineManagerBean implements MeasurementBaselineManage @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void saveNewBaselines(List<MeasurementBaseline> baselines) { for (MeasurementBaseline baseline : baselines) { - entityManager.merge(baseline); + MeasurementSchedule schedule = new MeasurementSchedule(); + schedule.setId(baseline.getScheduleId()); + baseline.setSchedule(schedule); + this.entityManager.merge(baseline); } }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerLocal.java index af6145a..35b8099 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementBaselineManagerLocal.java @@ -24,7 +24,6 @@ import javax.ejb.Local;
import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.measurement.MeasurementBaseline; -import org.rhq.core.domain.measurement.MeasurementSchedule; import org.rhq.core.domain.resource.Resource;
/** @@ -73,7 +72,7 @@ public interface MeasurementBaselineManagerLocal { * will be called repeatedly during baseline calculations to get all of the necessary * schedules. */ - List<MeasurementSchedule> getSchedulesWithoutBaselines(); + List<Integer> getSchedulesWithoutBaselines();
/** * Given a list of schedules, this method calculates and stores baselines using the @@ -87,7 +86,7 @@ public interface MeasurementBaselineManagerLocal { * is treated as a duration. For example, a value of 259200000 * would be treated as 3 days. */ - void calculateBaselines(List<MeasurementSchedule> schedules, long olderThan, long amountOfData); + void calculateBaselines(List<Integer> schedules, long olderThan, long amountOfData);
/** * Persists the newly calculated baselines. @@ -148,7 +147,7 @@ public interface MeasurementBaselineManagerLocal { /** * Return a list of {@link MeasurementBaseline} objects for the {@link Resource} represented by the given id. * - * @param subject the user request to view the baseline history for the given resource + * @param subject the user request to view the baseline history for the given resource * @param resourceId the id of the resource whose baselines are to be returned * * @return a list of baselines for all measurements scheduled on the given resource diff --git a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/MetricsBaselineCalculator.java b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/MetricsBaselineCalculator.java index 6242df6..ef7d092 100644 --- a/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/MetricsBaselineCalculator.java +++ b/modules/enterprise/server/server-metrics/src/main/java/org/rhq/server/metrics/MetricsBaselineCalculator.java @@ -31,7 +31,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.measurement.MeasurementBaseline; -import org.rhq.core.domain.measurement.MeasurementSchedule; import org.rhq.server.metrics.domain.AggregateSimpleNumericMetric; import org.rhq.server.metrics.domain.AggregateType;
@@ -48,12 +47,12 @@ public class MetricsBaselineCalculator { this.metricsDAO = metricsDAO; }
- public List<MeasurementBaseline> calculateBaselines(List<MeasurementSchedule> schedules, long startTime, + public List<MeasurementBaseline> calculateBaselines(List<Integer> schedules, long startTime, long endTime) { List<MeasurementBaseline> calculatedBaselines = new ArrayList<MeasurementBaseline>();
MeasurementBaseline measurementBaseline; - for (MeasurementSchedule schedule : schedules) { + for (Integer schedule : schedules) { measurementBaseline = this.calculateBaseline(schedule, startTime, endTime); if (measurementBaseline != null) { calculatedBaselines.add(measurementBaseline); @@ -63,9 +62,9 @@ public class MetricsBaselineCalculator { return calculatedBaselines; }
- private MeasurementBaseline calculateBaseline(MeasurementSchedule schedule, long startTime, long endTime) { - Iterable<AggregateSimpleNumericMetric> metrics = this.metricsDAO.findAggregatedSimpleOneHourMetric( - schedule.getId(), startTime, endTime); + private MeasurementBaseline calculateBaseline(Integer schedule, long startTime, long endTime) { + Iterable<AggregateSimpleNumericMetric> metrics = this.metricsDAO.findAggregatedSimpleOneHourMetric(schedule, + startTime, endTime);
if (metrics != null && metrics.iterator() != null && metrics.iterator().hasNext()) { ArithmeticMeanCalculator mean = new ArithmeticMeanCalculator(); @@ -104,7 +103,7 @@ public class MetricsBaselineCalculator { baseline.setMax(max); baseline.setMin(min); baseline.setMean(mean.getArithmeticMean()); - baseline.setSchedule(schedule); + baseline.setScheduleId(schedule);
if (log.isDebugEnabled()) { log.debug("Calculated baseline: " + baseline.toString()); @@ -113,12 +112,6 @@ public class MetricsBaselineCalculator { return baseline; }
- MeasurementBaseline baseline = new MeasurementBaseline(); - baseline.setMax(Double.NaN); - baseline.setMin(Double.NaN); - baseline.setMean(Double.NaN); - baseline.setSchedule(schedule); - - return baseline; + return null; } } diff --git a/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/MetricsBaselineCalculatorTest.java b/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/MetricsBaselineCalculatorTest.java index 2b58222..1137dca 100644 --- a/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/MetricsBaselineCalculatorTest.java +++ b/modules/enterprise/server/server-metrics/src/test/java/org/rhq/server/metrics/MetricsBaselineCalculatorTest.java @@ -27,7 +27,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -import static org.rhq.test.AssertUtils.assertPropertiesMatch; import static org.testng.Assert.assertEquals;
import java.util.ArrayList; @@ -44,7 +43,6 @@ import org.testng.annotations.ObjectFactory; import org.testng.annotations.Test;
import org.rhq.core.domain.measurement.MeasurementBaseline; -import org.rhq.core.domain.measurement.MeasurementSchedule; import org.rhq.server.metrics.domain.AggregateSimpleNumericMetric; import org.rhq.server.metrics.domain.AggregateType;
@@ -66,7 +64,6 @@ public class MetricsBaselineCalculatorTest {
@Test public void noCalculationTest() throws Exception { - //tell the method story as it happens: mock dependencies and configure //those dependencies to get the method under test to completion. StorageSession mockSession = mock(StorageSession.class); @@ -74,34 +71,24 @@ public class MetricsBaselineCalculatorTest { PowerMockito.whenNew(MetricsDAO.class).withParameterTypes(StorageSession.class, MetricsConfiguration.class) .withArguments(eq(mockSession), eq(metricsConfiguration)).thenReturn(mockMetricsDAO);
- when(mockMetricsDAO.findAggregatedSimpleOneHourMetric(eq(1), eq(0), - eq(1))).thenReturn(new ArrayList<AggregateSimpleNumericMetric>()); + when(mockMetricsDAO.findAggregatedSimpleOneHourMetric(eq(1), eq(0), eq(1))).thenReturn( + new ArrayList<AggregateSimpleNumericMetric>());
- MeasurementSchedule mockSchedule = mock(MeasurementSchedule.class); - when(mockSchedule.getId()).thenReturn(0); + int expectedScheduleId = 2567;
//create object to test and inject required dependencies MetricsBaselineCalculator objectUnderTest = new MetricsBaselineCalculator(new MetricsDAO(mockSession, metricsConfiguration));
//run code under test - List<MeasurementBaseline> result = objectUnderTest.calculateBaselines(Arrays.asList(mockSchedule), 0, 1); + List<MeasurementBaseline> result = objectUnderTest.calculateBaselines(Arrays.asList(expectedScheduleId), 0, 1);
//verify the results (Assert and mock verification) - assertEquals(result.size(), 1, "Expected to get back one baseline"); - MeasurementBaseline expected = new MeasurementBaseline(); - expected.setSchedule(mockSchedule); - expected.setMax(Double.NaN); - expected.setMin(Double.NaN); - expected.setMean(Double.NaN); - - assertPropertiesMatch("", expected, result.get(0), "computeTime"); + assertEquals(result.size(), 0, "No baselines expected");
verify(mockMetricsDAO, times(1)).findAggregatedSimpleOneHourMetric(any(Integer.class), any(Integer.class), any(Integer.class)); verifyNoMoreInteractions(mockMetricsDAO); - - verify(mockSchedule, times(1)).getId(); }
@Test @@ -138,7 +125,7 @@ public class MetricsBaselineCalculatorTest { } }
- int expectedScheduleId= 567; + int expectedScheduleId = 1567; long expectedStartTime = 135; long expectedEndTime = 246; long beforeComputeTime = System.currentTimeMillis(); @@ -154,15 +141,12 @@ public class MetricsBaselineCalculatorTest { mockMetricsDAO.findAggregatedSimpleOneHourMetric(eq(expectedScheduleId), eq(expectedStartTime), eq(expectedEndTime))).thenReturn(randomData);
- MeasurementSchedule mockSchedule = mock(MeasurementSchedule.class); - when(mockSchedule.getId()).thenReturn(expectedScheduleId); - //create object to test and inject required dependencies MetricsBaselineCalculator objectUnderTest = new MetricsBaselineCalculator(new MetricsDAO(mockSession, metricsConfiguration));
//run code under test - List<MeasurementBaseline> result = objectUnderTest.calculateBaselines(Arrays.asList(mockSchedule), + List<MeasurementBaseline> result = objectUnderTest.calculateBaselines(Arrays.asList(expectedScheduleId), expectedStartTime, expectedEndTime);
//verify the results (Assert and mock verification) @@ -172,7 +156,7 @@ public class MetricsBaselineCalculatorTest { Assert.assertEquals(baselineResult.getMean(), average, TEST_PRECISION); Assert.assertEquals(baselineResult.getMax(), expectedMax, TEST_PRECISION); Assert.assertEquals(baselineResult.getMin(), expectedMin, TEST_PRECISION); - Assert.assertEquals(baselineResult.getSchedule(), mockSchedule); + Assert.assertEquals(baselineResult.getScheduleId(), expectedScheduleId); if (baselineResult.getComputeTime().getTime() > System.currentTimeMillis()) { Assert.fail("Back compute time, the computation was forward dated."); } @@ -183,10 +167,6 @@ public class MetricsBaselineCalculatorTest { verify(mockMetricsDAO, times(1)).findAggregatedSimpleOneHourMetric(eq(expectedScheduleId), eq(expectedStartTime), eq(expectedEndTime)); verifyNoMoreInteractions(mockMetricsDAO); - - verify(mockSchedule, times(2)).getId(); - verify(mockSchedule, times(1)).setBaseline(eq(baselineResult)); - verifyNoMoreInteractions(mockSchedule); }
@Test @@ -221,15 +201,12 @@ public class MetricsBaselineCalculatorTest { mockMetricsDAO.findAggregatedSimpleOneHourMetric(eq(expectedScheduleId), eq(expectedStartTime), eq(expectedEndTime))).thenReturn(randomData);
- MeasurementSchedule mockSchedule = mock(MeasurementSchedule.class); - when(mockSchedule.getId()).thenReturn(expectedScheduleId); - //create object to test and inject required dependencies MetricsBaselineCalculator objectUnderTest = new MetricsBaselineCalculator(new MetricsDAO(mockSession, metricsConfiguration));
//run code under test - List<MeasurementBaseline> result = objectUnderTest.calculateBaselines(Arrays.asList(mockSchedule), + List<MeasurementBaseline> result = objectUnderTest.calculateBaselines(Arrays.asList(expectedScheduleId), expectedStartTime, expectedEndTime);
//verify the results (Assert and mock verification) @@ -239,15 +216,10 @@ public class MetricsBaselineCalculatorTest { Assert.assertEquals(baselineResult.getMean(), average, TEST_PRECISION); Assert.assertEquals(baselineResult.getMax(), expectedMinMax); Assert.assertEquals(baselineResult.getMin(), expectedMinMax); - Assert.assertEquals(baselineResult.getSchedule(), mockSchedule); + Assert.assertEquals(baselineResult.getScheduleId(), expectedScheduleId);
verify(mockMetricsDAO, times(1)).findAggregatedSimpleOneHourMetric(eq(expectedScheduleId), eq(expectedStartTime), eq(expectedEndTime)); verifyNoMoreInteractions(mockMetricsDAO); - - verify(mockSchedule, times(2)).getId(); - verify(mockSchedule, times(1)).setBaseline(eq(baselineResult)); - verifyNoMoreInteractions(mockSchedule); } - }
commit f469c776f4b896d526402ebb47e3924acf811a74 Author: John Sanda jsanda@redhat.com Date: Sat Aug 17 18:47:37 2013 -0400
update status property for undeployment operation modes
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index 4d4596e..e0f278d 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -254,10 +254,17 @@ public class StorageNode implements Serializable { return Status.DOWN; } } + if (operationMode == OperationMode.DECOMMISSION || operationMode == OperationMode.UNANNOUNCE || + operationMode == OperationMode.REMOVE_MAINTENANCE || operationMode == OperationMode.UNINSTALL) { + if (errorMessage == null && failedOperation == null) { + return Status.LEAVING; + } else { + return Status.DOWN; + } + } if (operationMode == OperationMode.NORMAL) { return Status.NORMAL; } - // else operation mode is DOWN return Status.DOWN; }
commit 28ad34e1525450501ae0a835927dc62bfdcd4527 Author: John Sanda jsanda@redhat.com Date: Sat Aug 17 15:17:37 2013 -0400
add support for undeploying a node that is in a failed deployment state
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index fcf4526..04abeb88 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -250,9 +250,12 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN reset(); storageNodeOperationsHandler.performAddNodeMaintenance(subject, storageNode); default: - // For any other operation mode, the storage node should already be part of - // the cluster. - // TODO Make sure that the storage node is in fact part of the cluster + // TODO what do we do with/about maintenance mode? + + // We do not want to deploying a node that is in the process of being + // undeployed. It is too hard to make sure we are in an inconsistent state. + // Instead finishe the undeployment and redeploy the storage node. + throw new RuntimeException("Cannot deploy " + storageNode); } }
@@ -264,6 +267,12 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN reset(); storageNodeOperationsHandler.uninstall(subject, storageNode); break; + case ANNOUNCE: + case BOOTSTRAP: + reset(); + storageNodeOperationsHandler.unannounceStorageNode(subject, storageNode); + break; + case ADD_NODE_MAINTENANCE: case NORMAL: case DECOMMISSION: reset(); @@ -281,7 +290,8 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN storageNodeOperationsHandler.uninstall(subject, storageNode); break; default: - + // TODO what do we do with/about maintenance mode + throw new RuntimeException("Cannot undeploy " + storageNode); } }
commit d7b53fd524ac99dda87101dbb11858c7649ed5de Author: John Sanda jsanda@redhat.com Date: Sat Aug 17 14:36:04 2013 -0400
add a check to see if the node is already decommissioned
If has C* has already been decommissioned, i.e., its operation mode is DECOMMISSIONED, then trying the decommission operation again will result in C* throwing an exception which we could interpret as a failed operation. This makes the resource operation idempotent.
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java index a82992e..7455f5e 100644 --- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java +++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java @@ -273,10 +273,16 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper try { EmsConnection emsConnection = getEmsConnection(); EmsBean storageService = emsConnection.getBean("org.apache.cassandra.db:type=StorageService"); - Class<?>[] emptyParams = new Class<?>[0];
- EmsOperation operation = storageService.getOperation("decommission", emptyParams); - operation.invoke((Object[]) emptyParams); + EmsAttribute operationModeAttr = storageService.getAttribute("OperationMode"); + String operationMode = (String) operationModeAttr.refresh(); + if (operationMode.equals("DECOMMISSIONED")) { + log.info("The storage node at " + getResourceContext().getResourceKey() + " is already decommissioned."); + } else { + Class<?>[] emptyParams = new Class<?>[0]; + EmsOperation operation = storageService.getOperation("decommission", emptyParams); + operation.invoke((Object[]) emptyParams); + } } catch (EmsInvocationException e) { result.setErrorMessage("Decommission operation failed: " + ThrowableUtil.getAllMessages(e)); }
commit 531e3d7784563107fa9ce3feb4b59c23980a668c Author: John Sanda jsanda@redhat.com Date: Sat Aug 17 14:00:27 2013 -0400
add support for resuming a failed undeployment
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 341cbc7..fcf4526 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -265,9 +265,13 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN storageNodeOperationsHandler.uninstall(subject, storageNode); break; case NORMAL: + case DECOMMISSION: reset(); storageNodeOperationsHandler.decommissionStorageNode(subject, storageNode); break; + case REMOVE_MAINTENANCE: + reset(); + storageNodeOperationsHandler.performRemoveNodeMaintenance(subject, storageNode); case UNANNOUNCE: reset(); storageNodeOperationsHandler.unannounceStorageNode(subject, storageNode); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index a30cfa7..f2fc108 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -78,9 +78,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa @EJB private ResourceManagerLocal resourceManager;
- @EJB - private ResourceFactoryManagerLocal resourceFactoryManager; - @Override public void announceStorageNode(Subject subject, StorageNode storageNode) { if (log.isInfoEnabled()) { @@ -150,19 +147,19 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
storageNode.setOperationMode(StorageNode.OperationMode.UNINSTALL);
- ResourceOperationSchedule schedule = new ResourceOperationSchedule(); - schedule.setResource(storageNode.getResource()); - schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subject); - schedule.setOperationName("uninstall"); - Configuration parameters = new Configuration(); - schedule.setParameters(parameters); - - operationManager.scheduleResourceOperation(subject, schedule); - -// Resource resource = storageNode.getResource(); -// storageNodeOperationsHandler.detachFromResource(storageNode); -// storageNodeOperationsHandler.deleteStorageNodeResource(subject, resource); + if (storageNode.getResource() == null) { + finishUninstall(subject, storageNode); + } else { + ResourceOperationSchedule schedule = new ResourceOperationSchedule(); + schedule.setResource(storageNode.getResource()); + schedule.setJobTrigger(JobTrigger.createNowTrigger()); + schedule.setSubject(subject); + schedule.setOperationName("uninstall"); + Configuration parameters = new Configuration(); + schedule.setParameters(parameters); + + operationManager.scheduleResourceOperation(subject, schedule); + } }
@Override @@ -173,13 +170,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
@Override - @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - public void deleteStorageNodeResource(Subject subject, Resource resource) { - log.info("Preparing to delete storage node resource " + resource); - resourceFactoryManager.deleteResource(subject, resource.getId()); - } - - @Override public void decommissionStorageNode(Subject subject, StorageNode storageNode) { log.info("Preparing to decommission " + storageNode);
@@ -272,20 +262,25 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
if (storageNode.getOperationMode() == StorageNode.OperationMode.DECOMMISSION) { storageNode.setOperationMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); - List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, - StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) - .getResultList(); - for (StorageNode node : clusterNodes) { - node.setMaintenancePending(true); - } - boolean runRepair = storageNode.isMaintenancePending(); - performRemoveNodeMaintenance(subjectManager.getOverlord(), clusterNodes.get(0), runRepair, - createPropertyListOfAddresses(SEEDS_LIST, clusterNodes)); + performRemoveNodeMaintenance(subjectManager.getOverlord(), storageNode); } else { log.info("Remove node maintenance has already been run for " + storageNode); } }
+ @Override + public void performRemoveNodeMaintenance(Subject subject, StorageNode storageNode) { + List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) + .getResultList(); + for (StorageNode node : clusterNodes) { + node.setMaintenancePending(true); + } + boolean runRepair = storageNode.isMaintenancePending(); + performRemoveNodeMaintenance(subjectManager.getOverlord(), clusterNodes.get(0), runRepair, + createPropertyListOfAddresses(SEEDS_LIST, clusterNodes)); + } + private void performRemoveNodeMaintenance(Subject subject, StorageNode storageNode, boolean runRepair, PropertyList seedsList) { if (log.isInfoEnabled()) { @@ -583,16 +578,18 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa break; default: // SUCCESS log.info("Successfully uninstalled " + storageNode + " from disk"); - Resource resource = storageNode.getResource(); - - log.info("Remove storage node resource " + resource + " from inventory"); - - storageNodeOperationsHandler.detachFromResource(storageNode); - resourceManager.uninventoryResource(getSubject(operationHistory), resource.getId()); + uninstall(getSubject(operationHistory), storageNode); + } + }
- log.info("Removing storage node entity " + storageNode + " from database"); - entityManager.remove(storageNode); + private void finishUninstall(Subject subject, StorageNode storageNode) { + if (storageNode.getResource() != null) { + log.info("Removing storage node resource " + storageNode.getResource() + " from inventory"); + storageNodeOperationsHandler.detachFromResource(storageNode); + resourceManager.uninventoryResource(subject, storageNode.getResource().getId()); } + log.info("Removing storage node entity " + storageNode + " from database"); + entityManager.remove(storageNode); }
private Subject getSubject(ResourceOperationHistory resourceOperationHistory) { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java index 7ed2c4d..5d08dd8 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java @@ -8,7 +8,6 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.operation.OperationHistory; import org.rhq.core.domain.operation.ResourceOperationHistory; -import org.rhq.core.domain.resource.Resource;
/** * @author John Sanda @@ -46,11 +45,11 @@ public interface StorageNodeOperationsHandlerLocal {
void detachFromResource(StorageNode storageNode);
- void deleteStorageNodeResource(Subject subject, Resource resource); - void decommissionStorageNode(Subject subject, StorageNode storageNode);
void performRemoveNodeMaintenanceIfNecessary(InetAddress storageNodeAddress);
+ void performRemoveNodeMaintenance(Subject subject, StorageNode storageNode); + void logError(StorageNode.OperationMode newStorageNodeOperationMode, String error, Exception e); }
commit 7e25cb04e6935259fac714fa5b507c6b2d23d51b Author: John Sanda jsanda@redhat.com Date: Sat Aug 17 12:06:03 2013 -0400
initial support for undeploying a storage node
Undeploying a storage node involves,
* removing the node from the cluster * updating existing nodes cassandra.yaml to no longer reference the node * updating the internode auth conf file for existing nodes * shutting down the node and purging its files from disk * removing the node's resource from inventory * deleting the StorageNode entity
There is stil a good bit of work left to do to handle various cases like going back to 1 node and kicking off the undeployment in all the various states.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index 48d5f83..4d4596e 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -24,6 +24,7 @@ package org.rhq.core.domain.cloud;
import java.io.Serializable;
+import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -146,7 +147,7 @@ public class StorageNode implements Serializable { private Resource resource;
@JoinColumn(name = "RESOURCE_OP_HIST_ID", referencedColumnName = "ID", nullable = true) - @OneToOne(optional = true) + @OneToOne(optional = true, cascade = {CascadeType.REMOVE}) private ResourceOperationHistory failedOperation;
// required for JPA @@ -261,17 +262,22 @@ public class StorageNode implements Serializable { }
public enum OperationMode { - + DECOMMISSION("Remove the storage node from service"), DOWN("This storage node is down"), // INSTALLED("This storage node is newly installed but not yet operational"), // MAINTENANCE("This storage node is in maintenance mode"), // NORMAL("This storage node is running normally"), ANNOUNCE("The storage node is installed but not yet part of the cluster. It is being announced so that it " + "can join the cluster."), + UNANNOUNCE("The storage node has been decommissioned and the cluster is being notified to stop accepting " + + "gossip from its IP address."), BOOTSTRAP("The storage is installed but not yet part of the cluster. It is getting bootstrapped into the " + "cluster"), ADD_NODE_MAINTENANCE("The storage node is running and is preparing to undergo routine maintenance that is " + - "necessary when a new node joins the cluster."); + "necessary when a new node joins the cluster."), + REMOVE_MAINTENANCE("The storage node is no longer part of the cluster. Remaining storage node are " + + "undergoing cluster maintenance due to the topology change."), + UNINSTALL("The storage node is being removed from inventory and its bits on disk are getting purged.");
public final String message;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 5cce984..341cbc7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -256,6 +256,31 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN } }
+ @Override + public void undeployStorageNode(Subject subject, StorageNode storageNode) { + storageNode = entityManager.find(StorageNode.class, storageNode.getId()); + switch (storageNode.getOperationMode()) { + case INSTALLED: + reset(); + storageNodeOperationsHandler.uninstall(subject, storageNode); + break; + case NORMAL: + reset(); + storageNodeOperationsHandler.decommissionStorageNode(subject, storageNode); + break; + case UNANNOUNCE: + reset(); + storageNodeOperationsHandler.unannounceStorageNode(subject, storageNode); + break; + case UNINSTALL: + reset(); + storageNodeOperationsHandler.uninstall(subject, storageNode); + break; + default: + + } + } + private void reset() { for (StorageNode storageNode : getStorageNodes()) { storageNode.setErrorMessage(null); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java index 75a795c..58a06a7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java @@ -170,4 +170,6 @@ public interface StorageNodeManagerLocal { StorageNode createStorageNode(Resource resource);
void deployStorageNode(Subject subject, StorageNode storageNode); + + void undeployStorageNode(Subject subject, StorageNode storageNode); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java index 2255299..7ffb2a6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java @@ -98,4 +98,6 @@ public interface StorageNodeManagerRemote { PageList<Alert> findAllStorageNodeAlerts(Subject subject, StorageNode storageNode);
void deployStorageNode(Subject sbubject, StorageNode storageNode); + + void undeployStorageNode(Subject subject, StorageNode storageNode); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java index 7db95fb..bd2efbe 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java @@ -41,6 +41,8 @@ public class StorageClusterMonitor implements StorageStateListener { @Override public void onStorageNodeRemoved(InetAddress address) { log.info("Storage node at " + address.getHostAddress() + " has been removed from the cluster"); + StorageNodeOperationsHandlerLocal storageNodeOperationsHandler = LookupUtil.getStorageNodeOperationsHandler(); + storageNodeOperationsHandler.performRemoveNodeMaintenanceIfNecessary(address); }
@Override diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index 4969c46..a30cfa7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -2,7 +2,6 @@ package org.rhq.enterprise.server.storage;
import java.net.InetAddress; import java.util.ArrayList; -import java.util.LinkedList; import java.util.List;
import javax.ejb.Asynchronous; @@ -35,6 +34,8 @@ import org.rhq.enterprise.server.auth.SessionManager; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal; import org.rhq.enterprise.server.operation.OperationManagerLocal; +import org.rhq.enterprise.server.resource.ResourceFactoryManagerLocal; +import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.server.metrics.StorageSession;
/** @@ -74,6 +75,12 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa @EJB private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler;
+ @EJB + private ResourceManagerLocal resourceManager; + + @EJB + private ResourceFactoryManagerLocal resourceFactoryManager; + @Override public void announceStorageNode(Subject subject, StorageNode storageNode) { if (log.isInfoEnabled()) { @@ -103,7 +110,33 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa schedule.setResource(clusterNode.getResource()); schedule.setJobTrigger(JobTrigger.createNowTrigger()); schedule.setSubject(subject); - schedule.setOperationName("updateKnownNodes"); + schedule.setOperationName("announce"); + Configuration parameters = new Configuration(); + parameters.put(addresses); + schedule.setParameters(parameters); + + operationManager.scheduleResourceOperation(subject, schedule); + } + + @Override + public void unannounceStorageNode(Subject subject, StorageNode storageNode) { + log.info("Unannouncing " + storageNode); + + storageNode.setOperationMode(StorageNode.OperationMode.UNANNOUNCE); + List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); + for (StorageNode clusterNode : clusterNodes) { + clusterNode.setMaintenancePending(true); + } + unannounceStorageNode(subject, clusterNodes.get(0), createPropertyListOfAddresses("addresses", clusterNodes)); + } + + private void unannounceStorageNode(Subject subject, StorageNode clusterNode, PropertyList addresses) { + ResourceOperationSchedule schedule = new ResourceOperationSchedule(); + schedule.setResource(clusterNode.getResource()); + schedule.setJobTrigger(JobTrigger.createNowTrigger()); + schedule.setSubject(subject); + schedule.setOperationName("unannounce"); Configuration parameters = new Configuration(); parameters.put(addresses); schedule.setParameters(parameters); @@ -112,10 +145,69 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
@Override + public void uninstall(Subject subject, StorageNode storageNode) { + log.info("Uninstalling " + storageNode); + + storageNode.setOperationMode(StorageNode.OperationMode.UNINSTALL); + + ResourceOperationSchedule schedule = new ResourceOperationSchedule(); + schedule.setResource(storageNode.getResource()); + schedule.setJobTrigger(JobTrigger.createNowTrigger()); + schedule.setSubject(subject); + schedule.setOperationName("uninstall"); + Configuration parameters = new Configuration(); + schedule.setParameters(parameters); + + operationManager.scheduleResourceOperation(subject, schedule); + +// Resource resource = storageNode.getResource(); +// storageNodeOperationsHandler.detachFromResource(storageNode); +// storageNodeOperationsHandler.deleteStorageNodeResource(subject, resource); + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void detachFromResource(StorageNode storageNode) { + storageNode.setResource(null); + storageNode.setFailedOperation(null); + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void deleteStorageNodeResource(Subject subject, Resource resource) { + log.info("Preparing to delete storage node resource " + resource); + resourceFactoryManager.deleteResource(subject, resource.getId()); + } + + @Override + public void decommissionStorageNode(Subject subject, StorageNode storageNode) { + log.info("Preparing to decommission " + storageNode); + + storageNode.setOperationMode(StorageNode.OperationMode.DECOMMISSION); + List<StorageNode> storageNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); + storageNodes.add(storageNode); + + boolean runRepair = updateSchemaIfNecessary(storageNodes); + // This is a bit of a hack since the maintenancePending flag is really intended to + // queue up storage nodes during cluster maintenance operations. + storageNode.setMaintenancePending(runRepair); + + ResourceOperationSchedule schedule = new ResourceOperationSchedule(); + schedule.setOperationName("decommission"); + schedule.setResource(storageNode.getResource()); + schedule.setJobTrigger(JobTrigger.createNowTrigger()); + schedule.setSubject(subject); + schedule.setParameters(new Configuration()); + + operationManager.scheduleResourceOperation(subject, schedule); + } + + @Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void logError(StorageNode.OperationMode newStorageNodeOperationMode, String error, Exception e) { try { - StorageNode newStorageNode = findNewStorgeNode(newStorageNodeOperationMode); + StorageNode newStorageNode = findStorageNodeByMode(newStorageNodeOperationMode); newStorageNode.setErrorMessage(error + " Check the server log for details. Root cause: " + ThrowableUtil.getRootCause(e).getMessage()); } catch (Exception e1) { @@ -157,8 +249,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa log.info("Running addNodeMaintenance for storage node " + storageNode); }
- Subject overlord = subjectManager.getOverlord(); - ResourceOperationSchedule schedule = new ResourceOperationSchedule(); schedule.setResource(storageNode.getResource()); schedule.setJobTrigger(JobTrigger.createNowTrigger()); @@ -172,7 +262,50 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
schedule.setParameters(config);
- operationManager.scheduleResourceOperation(overlord, schedule); + operationManager.scheduleResourceOperation(subject, schedule); + } + + @Override + public void performRemoveNodeMaintenanceIfNecessary(InetAddress storageNodeAddress) { + StorageNode storageNode = entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, + StorageNode.class).setParameter("address", storageNodeAddress.getHostAddress()).getSingleResult(); + + if (storageNode.getOperationMode() == StorageNode.OperationMode.DECOMMISSION) { + storageNode.setOperationMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); + List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) + .getResultList(); + for (StorageNode node : clusterNodes) { + node.setMaintenancePending(true); + } + boolean runRepair = storageNode.isMaintenancePending(); + performRemoveNodeMaintenance(subjectManager.getOverlord(), clusterNodes.get(0), runRepair, + createPropertyListOfAddresses(SEEDS_LIST, clusterNodes)); + } else { + log.info("Remove node maintenance has already been run for " + storageNode); + } + } + + private void performRemoveNodeMaintenance(Subject subject, StorageNode storageNode, boolean runRepair, + PropertyList seedsList) { + if (log.isInfoEnabled()) { + log.info("Running remove node maintenance for storage node " + storageNode); + } + + ResourceOperationSchedule schedule = new ResourceOperationSchedule(); + schedule.setResource(storageNode.getResource()); + schedule.setJobTrigger(JobTrigger.createNowTrigger()); + schedule.setSubject(subject); + schedule.setOperationName("removeNodeMaintenance"); + + Configuration config = new Configuration(); + config.put(seedsList); + config.put(new PropertySimple(RUN_REPAIR_PROPERTY, runRepair)); + config.put(new PropertySimple(UPDATE_SEEDS_LIST, Boolean.TRUE)); + + schedule.setParameters(config); + + operationManager.scheduleResourceOperation(subject, schedule); }
@Override @@ -187,9 +320,9 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return; }
- if (resourceOperationHistory.getOperationDefinition().getName().equals("updateKnownNodes")) { + if (resourceOperationHistory.getOperationDefinition().getName().equals("announce")) { try { - storageNodeOperationsHandler.handleUpdateKnownNodes(resourceOperationHistory); + storageNodeOperationsHandler.handleAnnounce(resourceOperationHistory); } catch (Exception e) { String msg = "Aborting storage node deployment due to unexpected error while announcing cluster nodes."; log.error(msg, e); @@ -212,13 +345,44 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa log.error(msg, e); storageNodeOperationsHandler.logError(StorageNode.OperationMode.ADD_NODE_MAINTENANCE, msg, e); } + } else if (operationHistory.getOperationDefinition().getName().equals("decommission")) { + try { + storageNodeOperationsHandler.handleDecommission(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting undeployment due to unexpected error while decommissioning storage node."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.DECOMMISSION, msg, e); + } + } else if (operationHistory.getOperationDefinition().getName().equals("removeNodeMaintenance")) { + try { + storageNodeOperationsHandler.handleRemoveNodeMaintenance(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting undeployment due to unexpected error while performing remove node maintenance."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.REMOVE_MAINTENANCE, msg, e); + } + } else if (operationHistory.getOperationDefinition().getName().equals("unannounce")) { + try { + storageNodeOperationsHandler.handleUnannounce(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting undeployment due to unexpected error while performing unannouncement."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.UNANNOUNCE, msg, e); + } + } else if (operationHistory.getOperationDefinition().getName().equals("uninstall")) { + try { + storageNodeOperationsHandler.handleUninstall(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting undeployment due to unexpected error while uninstalling."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.UNINSTALL, msg, e); + } } - }
@Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - public void handleUpdateKnownNodes(ResourceOperationHistory resourceOperationHistory) { + public void handleAnnounce(ResourceOperationHistory resourceOperationHistory) { StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); StorageNode newStorageNode = null; switch (resourceOperationHistory.getStatus()) { @@ -226,11 +390,11 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // nothing to do here return; case CANCELED: - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); - operationCanceled(storageNode, resourceOperationHistory, newStorageNode); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ANNOUNCE); + deploymentOperationCanceled(storageNode, resourceOperationHistory, newStorageNode); case FAILURE: - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); - operationFailed(storageNode, resourceOperationHistory, newStorageNode); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ANNOUNCE); + deploymentOperationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS storageNode.setMaintenancePending(false); @@ -238,7 +402,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa PropertyList addresses = parameters.getList("addresses"); StorageNode nextNode = takeFromMaintenanceQueue();
- newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ANNOUNCE); Subject subject = getSubject(resourceOperationHistory);
if (nextNode == null) { @@ -253,6 +417,41 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
@Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handleUnannounce(ResourceOperationHistory operationHistory) { + StorageNode storageNode = findStorageNode(operationHistory.getResource()); + StorageNode removedStorageNode = null; + switch (operationHistory.getStatus()) { + case INPROGRESS: + // nothing to do here + break; + case CANCELED: + removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); + undeploymentOperationCanceled(storageNode, operationHistory, removedStorageNode); + break; + case FAILURE: + removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); + deploymentOperationFailed(storageNode, operationHistory, removedStorageNode); + break; + default: // SUCCESS + storageNode.setMaintenancePending(false); + + removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.UNANNOUNCE); + StorageNode nextNode = takeFromMaintenanceQueue(); + Subject subject = getSubject(operationHistory); + Configuration params = operationHistory.getParameters(); + PropertyList addresses = params.getList("addresses"); + + if (nextNode == null) { + log.info("Successfully unannounced " + removedStorageNode + " to storage cluster"); + uninstall(getSubject(operationHistory), removedStorageNode); + } else { + unannounceStorageNode(subject, nextNode, addresses.deepCopy(false)); + } + } + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void handlePrepareForBootstrap(ResourceOperationHistory resourceOperationHistory) { StorageNode newStorageNode = findStorageNode(resourceOperationHistory.getResource()); switch (resourceOperationHistory.getStatus()) { @@ -264,10 +463,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // If the operation is canceled the plugin will get an InterruptedException. // The actual bootstrapping may very well complete so we need to add in some // checks to find out if the node is up and part of the cluster. - operationCanceled(newStorageNode, resourceOperationHistory); + deploymentOperationCanceled(newStorageNode, resourceOperationHistory); return; case FAILURE: - operationFailed(newStorageNode, resourceOperationHistory); + deploymentOperationFailed(newStorageNode, resourceOperationHistory); return; default: // SUCCESS // Nothing to do because we wait for the C* driver to notify us that the @@ -285,24 +484,22 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // nothing to do here return; case CANCELED: - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); - operationCanceled(storageNode, resourceOperationHistory, newStorageNode); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + deploymentOperationCanceled(storageNode, resourceOperationHistory, newStorageNode); return; case FAILURE: - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); - operationFailed(storageNode, resourceOperationHistory, newStorageNode); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + deploymentOperationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS - if (log.isInfoEnabled()) { - log.info("Finished cluster maintenance for " + storageNode + " for addition of new node"); - } + log.info("Finished running add node maintenance for " + storageNode); storageNode.setMaintenancePending(false); StorageNode nextNode = takeFromMaintenanceQueue();
if (nextNode == null) { - log.info("Finished running cluster maintenance for addition of new node"); + log.info("Finished running add node maintenance on all cluster nodes"); // TODO replace this with an UPDATE statement - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + newStorageNode = findStorageNodeByMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); newStorageNode.setOperationMode(StorageNode.OperationMode.NORMAL); } else { Configuration parameters = resourceOperationHistory.getParameters(); @@ -314,56 +511,176 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } }
+ @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handleRemoveNodeMaintenance(ResourceOperationHistory operationHistory) { + StorageNode storageNode = findStorageNode(operationHistory.getResource()); + StorageNode removedStorageNode = null; + switch (operationHistory.getStatus()) { + case INPROGRESS: + // nothing to do here + break; + case CANCELED: + removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); + undeploymentOperationCanceled(storageNode, operationHistory, removedStorageNode); + break; + case FAILURE: + removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); + undeploymentOperationFailed(storageNode, operationHistory, removedStorageNode); + break; + default: // SUCCESS + log.info("Finished remove node maintenance for " + storageNode); + storageNode.setMaintenancePending(false); + StorageNode nextNode = takeFromMaintenanceQueue(); + + if (nextNode == null) { + log.info("Finished running remove node maintenance on all cluster nodes"); + // TODO replace this with an UPDATE statement + removedStorageNode = findStorageNodeByMode(StorageNode.OperationMode.REMOVE_MAINTENANCE); + unannounceStorageNode(getSubject(operationHistory), removedStorageNode); + } else { + Configuration parameters = operationHistory.getParameters(); + boolean runRepair = parameters.getSimple(RUN_REPAIR_PROPERTY).getBooleanValue(); + PropertyList seedsList = parameters.getList(SEEDS_LIST).deepCopy(false); + Subject subject = getSubject(operationHistory); + performRemoveNodeMaintenance(subject, nextNode, runRepair, seedsList); + } + } + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handleDecommission(ResourceOperationHistory operationHistory) { + StorageNode storageNode = findStorageNode(operationHistory.getResource()); + switch (operationHistory.getStatus()) { + case INPROGRESS: + // nothing do to here + break; + case CANCELED: + undeploymentOperationCanceled(storageNode, operationHistory); + break; + case FAILURE: + undeploymentOperationFailed(storageNode, operationHistory); + break; + default: // SUCCESS + log.info("Successfully decommissioned " + storageNode); + } + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handleUninstall(ResourceOperationHistory operationHistory) { + StorageNode storageNode = findStorageNode(operationHistory.getResource()); + switch (operationHistory.getStatus()) { + case INPROGRESS: + // nothing to do here + break; + case CANCELED: + undeploymentOperationCanceled(storageNode, operationHistory); + break; + case FAILURE: + undeploymentOperationFailed(storageNode, operationHistory); + break; + default: // SUCCESS + log.info("Successfully uninstalled " + storageNode + " from disk"); + Resource resource = storageNode.getResource(); + + log.info("Remove storage node resource " + resource + " from inventory"); + + storageNodeOperationsHandler.detachFromResource(storageNode); + resourceManager.uninventoryResource(getSubject(operationHistory), resource.getId()); + + log.info("Removing storage node entity " + storageNode + " from database"); + entityManager.remove(storageNode); + } + } + private Subject getSubject(ResourceOperationHistory resourceOperationHistory) { Subject subject = subjectManager.getSubjectByName(resourceOperationHistory.getSubjectName()); return SessionManager.getInstance().put(subject); }
- private void operationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, + private void deploymentOperationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, StorageNode newStorageNode) { - log.error("Deployment has been aborted due to canceled operation [" + + operationCanceled(storageNode, operationHistory, newStorageNode, "Deployment"); + } + + private void undeploymentOperationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, + StorageNode removedStorageNode) { + operationCanceled(storageNode, operationHistory, removedStorageNode, "Undeployment"); + } + + private void operationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, + StorageNode movingNode, String opType) { + log.error(opType + " has been aborted due to canceled operation [" + operationHistory.getOperationDefinition().getDisplayName() + " on " + storageNode.getResource() + ": " + operationHistory.getErrorMessage());
- newStorageNode.setErrorMessage("Deployment has been aborted due to canceled resource operation on " + + movingNode.setErrorMessage(opType + " has been aborted due to canceled resource operation on " + storageNode.getAddress()); - storageNode.setErrorMessage("Deployment of " + newStorageNode.getAddress() + " has been aborted due " + + storageNode.setErrorMessage(opType + " of " + movingNode.getAddress() + " has been aborted due " + "to cancellation of resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); storageNode.setFailedOperation(operationHistory); }
- private void operationCanceled(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { - log.error("Deployment has been aborted due to canceled operation [" + - operationHistory.getOperationDefinition().getDisplayName() + " on " + newStorageNode.getResource() + + private void deploymentOperationCanceled(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { + operationCanceled(newStorageNode, operationHistory, "Deployment"); + } + + private void undeploymentOperationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory) { + operationCanceled(storageNode, operationHistory, "Undeployment"); + } + + private void operationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, String opType) { + log.error(opType + " has been aborted due to canceled operation [" + + operationHistory.getOperationDefinition().getDisplayName() + " on " + storageNode.getResource() + ": " + operationHistory.getErrorMessage());
- newStorageNode.setErrorMessage("Deployment has been aborted due to canceled resource operation [" + + storageNode.setErrorMessage(opType + " has been aborted due to canceled resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); - newStorageNode.setFailedOperation(operationHistory); + storageNode.setFailedOperation(operationHistory); }
- private void operationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, + private void deploymentOperationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, StorageNode newStorageNode) { - log.error("Deployment has been aborted due to failed operation [" + - operationHistory.getOperationDefinition().getDisplayName() + "] on " + storageNode.getResource() + - ": " + operationHistory.getErrorMessage()); + operationFailed(storageNode, operationHistory, newStorageNode, "Deployment"); + }
- newStorageNode.setErrorMessage("Deployment has been aborted due to failed resource operation on " + - storageNode.getAddress()); - storageNode.setErrorMessage("Deployment of " + newStorageNode.getAddress() + " has been aborted due " + - "to failed resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); - storageNode.setFailedOperation(operationHistory); + private void undeploymentOperationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, + StorageNode removedNode) { + operationFailed(storageNode, operationHistory, removedNode, "Undeployment"); + } + + private void deploymentOperationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory) { + operationFailed(storageNode, operationHistory, "Deployment"); + } + + private void undeploymentOperationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory) { + operationFailed(storageNode, operationHistory, "Undeployment"); }
- private void operationFailed(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { - log.error("Deployment has been aborted due to failed operation [" + - operationHistory.getOperationDefinition().getDisplayName() + "] on " + newStorageNode.getResource() + + private void operationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, String opType) { + log.error(opType + " has been aborted due to failed operation [" + + operationHistory.getOperationDefinition().getDisplayName() + "] on " + storageNode.getResource() + ": " + operationHistory.getErrorMessage());
- newStorageNode.setErrorMessage("Deployment has been aborted due to failed resource operation [" + + storageNode.setErrorMessage(opType + " has been aborted due to failed resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); - newStorageNode.setFailedOperation(operationHistory); + storageNode.setFailedOperation(operationHistory); + } + + private void operationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, + StorageNode movingNode, String opType) { + log.error(opType + " has been aborted due to failed operation [" + + operationHistory.getOperationDefinition().getDisplayName() + "] on " + storageNode.getResource() + + ": " + operationHistory.getErrorMessage()); + + movingNode.setErrorMessage(opType + " has been aborted due to failed resource operation on " + + storageNode.getAddress()); + storageNode.setErrorMessage(opType + " of " + movingNode.getAddress() + " has been aborted due " + + "to failed resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); + storageNode.setFailedOperation(operationHistory); }
private StorageNode findStorageNode(Resource resource) { @@ -417,7 +734,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return storageNodes.get(0); }
- private StorageNode findNewStorgeNode(StorageNode.OperationMode operationMode) { + private StorageNode findStorageNodeByMode(StorageNode.OperationMode operationMode) { return entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class) .setParameter("operationMode", operationMode).getSingleResult(); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java index 83b0ce5..7ed2c4d 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java @@ -8,6 +8,7 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.operation.OperationHistory; import org.rhq.core.domain.operation.ResourceOperationHistory; +import org.rhq.core.domain.resource.Resource;
/** * @author John Sanda @@ -17,19 +18,39 @@ public interface StorageNodeOperationsHandlerLocal { @Asynchronous void handleOperationUpdateIfNecessary(OperationHistory operationHistory);
- void handleUpdateKnownNodes(ResourceOperationHistory operationHistory); + void handleAnnounce(ResourceOperationHistory operationHistory); + + void handleUnannounce(ResourceOperationHistory operationHistory);
void handlePrepareForBootstrap(ResourceOperationHistory operationHistory);
void handleAddNodeMaintenance(ResourceOperationHistory operationHistory);
+ void handleRemoveNodeMaintenance(ResourceOperationHistory operationHistory); + + void handleDecommission(ResourceOperationHistory operationHistory); + + void handleUninstall(ResourceOperationHistory operationHistory); + void announceStorageNode(Subject subject, StorageNode storageNode);
+ void unannounceStorageNode(Subject subject, StorageNode storageNode); + void bootstrapStorageNode(Subject subject, StorageNode storageNode);
void performAddNodeMaintenanceIfNecessary(InetAddress storageNodeAddress);
void performAddNodeMaintenance(Subject subject, StorageNode storageNode);
+ void uninstall(Subject subject, StorageNode storageNode); + + void detachFromResource(StorageNode storageNode); + + void deleteStorageNodeResource(Subject subject, Resource resource); + + void decommissionStorageNode(Subject subject, StorageNode storageNode); + + void performRemoveNodeMaintenanceIfNecessary(InetAddress storageNodeAddress); + void logError(StorageNode.OperationMode newStorageNodeOperationMode, String error, Exception e); } diff --git a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java index 5692bea..1bf9683 100644 --- a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java +++ b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java @@ -67,7 +67,8 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone private static final String FREE_DISK_TO_DATA_SIZE_RATIO_METRIC_NAME = "Calculated.FreeDiskToDataSizeRatio"; private static final String TAKE_SNAPSHOT_OPERATION_NAME = "takeSnapshot"; private static final String[] MAINTENANCE_OPERATIONS = new String[] { "readRepair", "addNodeMaintenance", - "updateKnownNodes", "prepareForBootstrap", "prepareForUpgrade", "updateSeedsList", "updateConfiguration" }; + "removeNodeMaintenance", "announce", "unannounce", "prepareForBootstrap", "prepareForUpgrade", + "updateSeedsList", "updateConfiguration" };
static private final List<InjectedTemplate> injectedTemplates; static private final InjectedTemplate storageNodeHighHeapTemplate;
commit a48d538f936301f849b1092666e7f9e04221d274 Author: John Sanda jsanda@redhat.com Date: Sat Aug 17 11:57:38 2013 -0400
Implement storage node uninstall as resource operation
The uninstall task invovles purging the storage node bits from disk and removing it from inventory. I previously implemented this by implementing the DeleteResourceFacet. This was problematic though because the server side logic for the deploy/undeploy work flows are centered around resource operations.
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java index 64d672d..a82992e 100644 --- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java +++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java @@ -55,7 +55,6 @@ import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.pluginapi.configuration.ConfigurationFacet; import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport; -import org.rhq.core.pluginapi.inventory.DeleteResourceFacet; import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.operation.OperationFacet; @@ -71,8 +70,7 @@ import org.rhq.plugins.cassandra.util.KeyspaceService; /** * @author John Sanda */ -public class StorageNodeComponent extends CassandraNodeComponent implements OperationFacet, ConfigurationFacet, - DeleteResourceFacet { +public class StorageNodeComponent extends CassandraNodeComponent implements OperationFacet, ConfigurationFacet {
private Log log = LogFactory.getLog(StorageNodeComponent.class);
@@ -91,29 +89,6 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper configDelegate.updateResourceConfiguration(configurationUpdateReport); }
- @Override - public void deleteResource() throws Exception { - OperationResult shutdownResult = shutdownIfNecessary(); - if (shutdownResult.getErrorMessage() != null) { - throw new Exception("Cannot delete storage node [resourceKey: " + getResourceContext().getResourceKey() + - "]: " + shutdownResult.getErrorMessage()); - } - - log.info("Purging data directories"); - Configuration pluginConfig = getResourceContext().getPluginConfiguration(); - String yamlProp = pluginConfig.getSimpleValue("yamlConfiguration"); - File yamlFile = new File(yamlProp); - ConfigEditor yamlEditor = new ConfigEditor(yamlFile); - yamlEditor.load(); - purgeDataDirs(yamlEditor); - - File basedir = getBasedir(); - log.info("Purging installation directory " + basedir); - purgeDir(basedir); - - log.info("Finished deleting storage node " + getResourceContext().getResourceKey()); - } - private OperationResult shutdownIfNecessary() { log.info("Shutting down " + getResourceContext().getResourceKey());
@@ -159,14 +134,18 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper return readRepair(); } else if (name.equals("updateConfiguration")) { return updateConfiguration(parameters); - } else if (name.equals("updateKnownNodes")) { - return updateKnownNodes(parameters); + } else if (name.equals("announce")) { + return announce(parameters); + } else if (name.equals("unannounce")) { + return unannounce(parameters); } else if (name.equals("prepareForBootstrap")) { return prepareForBootstrap(parameters); } else if (name.equals("shutdown")) { return shutdownStorageNode(); } else if (name.equals("decommission")) { return decommission(); + } else if (name.equals("uninstall")) { + return uninstall(); } else { return super.invokeOperation(name, parameters); } @@ -304,6 +283,41 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper return result; }
+ private OperationResult uninstall() { + OperationResult result = new OperationResult(); + OperationResult shutdownResult = shutdownIfNecessary(); + if (shutdownResult.getErrorMessage() != null) { + result.setErrorMessage("Failed to shut down storage node: " + shutdownResult.getErrorMessage()); + } else { + File basedir = getBasedir(); + if (basedir.exists()) { + log.info("Purging data directories"); + Configuration pluginConfig = getResourceContext().getPluginConfiguration(); + String yamlProp = pluginConfig.getSimpleValue("yamlConfiguration"); + File yamlFile = new File(yamlProp); + ConfigEditor yamlEditor = new ConfigEditor(yamlFile); + yamlEditor.load(); + purgeDataDirs(yamlEditor); + + log.info("Purging installation directory " + basedir); + purgeDir(basedir); + + log.info("Finished deleting storage node " + getResourceContext().getResourceKey()); + } else { + log.info(basedir + " does not exist. Storage node files have already been purged."); + } + } + return result; + } + + private OperationResult announce(Configuration params) { + return updateKnownNodes(params); + } + + private OperationResult unannounce(Configuration params) { + return updateKnownNodes(params); + } + private OperationResult updateKnownNodes(Configuration params) { OperationResult result = new OperationResult();
diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml index 95c1723..5159b95 100644 --- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml @@ -12,8 +12,7 @@ name="RHQ Storage Node" discovery="StorageNodeDiscoveryComponent" class="StorageNodeComponent" - description="RHQ Storage Node" - createDeletePolicy="delete-only"> + description="RHQ Storage Node">
<subcategories> <subcategory name="Client Request Metrics" description="Client Request Metrics"/> @@ -67,7 +66,9 @@ </results> </operation>
- <operation name="decommission" description="Take the Cassandra node out of service"/> + <operation name="decommission" description="Take the storage node out of service"/> + + <operation name="uninstall" description="Removes all of the storage node files from disk"/>
<operation name="readRepair" description="Runs read repair on primar range of rhq and system_auth keyspaces"> <results> @@ -119,7 +120,18 @@ </results> </operation>
- <operation name="updateKnownNodes"> + <operation name="announce"> + <parameters> + <c:list-property name="addresses"> + <c:simple-property name="address"/> + </c:list-property> + </parameters> + <results> + <c:simple-property name="details"/> + </results> + </operation> + + <operation name="unannounce"> <parameters> <c:list-property name="addresses"> <c:simple-property name="address"/>
commit 409f7417f0fb5997bc2e8b8dbe8f5d90749454f5 Author: John Sanda jsanda@redhat.com Date: Fri Aug 16 22:00:19 2013 -0400
adding plugin support for decommissioning and uninstalling a storage node
diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java index a24a219..64d672d 100644 --- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java +++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java @@ -39,6 +39,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.sigar.SigarException; import org.mc4j.ems.connection.EmsConnection; +import org.mc4j.ems.connection.EmsInvocationException; import org.mc4j.ems.connection.bean.EmsBean; import org.mc4j.ems.connection.bean.attribute.EmsAttribute; import org.mc4j.ems.connection.bean.operation.EmsOperation; @@ -54,6 +55,7 @@ import org.rhq.core.domain.configuration.PropertyMap; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.pluginapi.configuration.ConfigurationFacet; import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport; +import org.rhq.core.pluginapi.inventory.DeleteResourceFacet; import org.rhq.core.pluginapi.inventory.ProcessScanResult; import org.rhq.core.pluginapi.inventory.ResourceContext; import org.rhq.core.pluginapi.operation.OperationFacet; @@ -69,7 +71,8 @@ import org.rhq.plugins.cassandra.util.KeyspaceService; /** * @author John Sanda */ -public class StorageNodeComponent extends CassandraNodeComponent implements OperationFacet, ConfigurationFacet { +public class StorageNodeComponent extends CassandraNodeComponent implements OperationFacet, ConfigurationFacet, + DeleteResourceFacet {
private Log log = LogFactory.getLog(StorageNodeComponent.class);
@@ -88,11 +91,54 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper configDelegate.updateResourceConfiguration(configurationUpdateReport); }
+ @Override + public void deleteResource() throws Exception { + OperationResult shutdownResult = shutdownIfNecessary(); + if (shutdownResult.getErrorMessage() != null) { + throw new Exception("Cannot delete storage node [resourceKey: " + getResourceContext().getResourceKey() + + "]: " + shutdownResult.getErrorMessage()); + } + + log.info("Purging data directories"); + Configuration pluginConfig = getResourceContext().getPluginConfiguration(); + String yamlProp = pluginConfig.getSimpleValue("yamlConfiguration"); + File yamlFile = new File(yamlProp); + ConfigEditor yamlEditor = new ConfigEditor(yamlFile); + yamlEditor.load(); + purgeDataDirs(yamlEditor); + + File basedir = getBasedir(); + log.info("Purging installation directory " + basedir); + purgeDir(basedir); + + log.info("Finished deleting storage node " + getResourceContext().getResourceKey()); + } + + private OperationResult shutdownIfNecessary() { + log.info("Shutting down " + getResourceContext().getResourceKey()); + + ProcessInfo process = getResourceContext().getNativeProcess(); + if (process == null) { + File pidFile = new File(getBinDir(), "cassandra.pid"); + if (pidFile.exists()) { + return shutdownStorageNode(); + } else { + return new OperationResult("Storage node is not running"); + } + } else { + return shutdownStorageNode(); + } + } + private File getBasedir() { Configuration pluginConfig = getResourceContext().getPluginConfiguration(); return new File(pluginConfig.getSimpleValue("baseDir")); }
+ private File getBinDir() { + return new File(getBasedir(), "bin"); + } + private File getConfDir() { return new File(getBasedir(), "conf"); } @@ -105,6 +151,8 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper public OperationResult invokeOperation(String name, Configuration parameters) throws Exception { if (name.equals("addNodeMaintenance")) { return nodeAdded(parameters); + } else if (name.equals("removeNodeMaintenance")) { + return nodeRemoved(parameters); } else if (name.equals("prepareForUpgrade")) { return prepareForUpgrade(parameters); } else if (name.equals("readRepair")) { @@ -117,6 +165,8 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper return prepareForBootstrap(parameters); } else if (name.equals("shutdown")) { return shutdownStorageNode(); + } else if (name.equals("decommission")) { + return decommission(); } else { return super.invokeOperation(name, parameters); } @@ -237,6 +287,23 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper return result; }
+ private OperationResult decommission() { + log.info("Decommissioning " + getResourceContext().getResourceKey()); + + OperationResult result = new OperationResult(); + try { + EmsConnection emsConnection = getEmsConnection(); + EmsBean storageService = emsConnection.getBean("org.apache.cassandra.db:type=StorageService"); + Class<?>[] emptyParams = new Class<?>[0]; + + EmsOperation operation = storageService.getOperation("decommission", emptyParams); + operation.invoke((Object[]) emptyParams); + } catch (EmsInvocationException e) { + result.setErrorMessage("Decommission operation failed: " + ThrowableUtil.getAllMessages(e)); + } + return result; + } + private OperationResult updateKnownNodes(Configuration params) { OperationResult result = new OperationResult();
@@ -295,11 +362,7 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper try { configEditor.load();
- purgeDir(new File(configEditor.getCommitLogDirectory())); - for (String dir : configEditor.getDataFileDirectories()) { - purgeDir(new File(dir)); - } - purgeDir(new File(configEditor.getSavedCachesDirectory())); + purgeDataDirs(configEditor);
log.info("Updating cluster settings");
@@ -357,6 +420,14 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper } }
+ private void purgeDataDirs(ConfigEditor configEditor) { + purgeDir(new File(configEditor.getCommitLogDirectory())); + for (String dir : configEditor.getDataFileDirectories()) { + purgeDir(new File(dir)); + } + purgeDir(new File(configEditor.getSavedCachesDirectory())); + } + private void purgeDir(File dir) { log.info("Purging " + dir); FileUtil.purge(dir, true); @@ -377,6 +448,14 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper }
private OperationResult nodeAdded(Configuration params) { + return performTopologyChangeMaintenance(params); + } + + private OperationResult nodeRemoved(Configuration params) { + return performTopologyChangeMaintenance(params); + } + + private OperationResult performTopologyChangeMaintenance(Configuration params) { boolean runRepair = params.getSimple("runRepair").getBooleanValue(); boolean updateSeedsList = params.getSimple("updateSeedsList").getBooleanValue();
diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml index cc01c9d..95c1723 100644 --- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml @@ -12,7 +12,8 @@ name="RHQ Storage Node" discovery="StorageNodeDiscoveryComponent" class="StorageNodeComponent" - description="RHQ Storage Node"> + description="RHQ Storage Node" + createDeletePolicy="delete-only">
<subcategories> <subcategory name="Client Request Metrics" description="Client Request Metrics"/> @@ -66,6 +67,8 @@ </results> </operation>
+ <operation name="decommission" description="Take the Cassandra node out of service"/> + <operation name="readRepair" description="Runs read repair on primar range of rhq and system_auth keyspaces"> <results> <c:list-property name="results"> @@ -97,6 +100,25 @@ </results> </operation>
+ <operation name="removeNodeMaintenance"> + <parameters> + <c:simple-property name="runRepair" type="boolean" default="true"/> + <c:simple-property name="updateSeedsList" type="boolean" default="true"/> + <c:list-property name="seedsList"> + <c:simple-property name="seed" type="string"/> + </c:list-property> + </parameters> + <results> + <c:list-property name="results"> + <c:map-property name="resultsMap"> + <c:simple-property name="task" type="string"/> + <c:simple-property name="succeeded" type="boolean"/> + <c:simple-property name="details" type="string"/> + </c:map-property> + </c:list-property> + </results> + </operation> + <operation name="updateKnownNodes"> <parameters> <c:list-property name="addresses">
commit e204ed6106c0050ad4ef689e1178c4601cb30177 Author: mtho11 mikecthompson@gmail.com Date: Thu Aug 15 21:56:44 2013 -0700
Fix refresh to keep graph open after auto-refresh.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java index ae51195..9bd1ea6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceDetailView.java @@ -114,6 +114,8 @@ public class ResourceDetailView extends
private ResourceComposite resourceComposite;
+ private MetricsResourceView metricsResourceView; + //private List<ResourceSelectListener> selectListeners = new ArrayList<ResourceSelectListener>();
private TwoLevelTab summaryTab; @@ -391,7 +393,10 @@ public class ResourceDetailView extends viewFactory = (!visible) ? null : new ViewFactory() { @Override public Canvas createView() { - return new MetricsResourceView(resource); + if(null == metricsResourceView){ + metricsResourceView = new MetricsResourceView(resource); + } + return metricsResourceView; } }; updateSubTab(this.monitoringTab, this.monitorMetrics, visible, visibleToIE8, viewFactory); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java index db9abd4..242efe0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/MetricsTableView.java @@ -81,6 +81,7 @@ import org.rhq.enterprise.gui.coregui.client.util.preferences.MeasurementUserPre public class MetricsTableView extends Table<MetricsViewDataSource> implements Refreshable {
private final Resource resource; + private boolean rendered = false; private final AbstractD3GraphListView abstractD3GraphListView;
private final MeasurementUserPreferences measurementUserPrefs; @@ -115,19 +116,22 @@ public class MetricsTableView extends Table<MetricsViewDataSource> implements Re ArrayList<ListGridField> fields = getDataSource().getListGridFields(); setListGridFields(fields.toArray(new ListGridField[0]));
- addTableAction(MSG.view_measureTable_getLive(), new ShowLiveDataTableAction(this)); - addExtraWidget(addToDashboardComponent, false); - addToDashboardComponent.disableAddToDashboardButton(); - metricsTableListGrid.addSelectionChangedHandler(new SelectionChangedHandler() { - @Override - public void onSelectionChanged(SelectionEvent selectionEvent) { - if (metricsTableListGrid.getSelectedRecords().length > 0) { - addToDashboardComponent.enableAddToDashboardButton(); - } else { - addToDashboardComponent.disableAddToDashboardButton(); + if(!rendered){ + addTableAction(MSG.view_measureTable_getLive(), new ShowLiveDataTableAction(this)); + addExtraWidget(addToDashboardComponent, false); + addToDashboardComponent.disableAddToDashboardButton(); + metricsTableListGrid.addSelectionChangedHandler(new SelectionChangedHandler() { + @Override + public void onSelectionChanged(SelectionEvent selectionEvent) { + if (metricsTableListGrid.getSelectedRecords().length > 0) { + addToDashboardComponent.enableAddToDashboardButton(); + } else { + addToDashboardComponent.disableAddToDashboardButton(); + } } - } - }); + }); + rendered = true; + } }
private static class ShowLiveDataTableAction implements TableAction {
commit 5ce350ae60dd09e338bcaf795dd929a0394affde Author: Jirka Kremser jkremser@redhat.com Date: Fri Aug 16 15:50:36 2013 +0200
Adding new component for editing the storage cluster configuration (stored in the system settings).
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageClusterSettings.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageClusterSettings.java new file mode 100644 index 0000000..661ad18 --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageClusterSettings.java @@ -0,0 +1,56 @@ +package org.rhq.core.domain.cloud; + +import java.io.Serializable; + +/** + * @author John Sanda + */ +public class StorageClusterSettings implements Serializable { + + private static final long serialVersionUID = 1; + + private int cqlPort; + + private int gossipPort; + + public int getCqlPort() { + return cqlPort; + } + + public void setCqlPort(int cqlPort) { + this.cqlPort = cqlPort; + } + + public int getGossipPort() { + return gossipPort; + } + + public void setGossipPort(int gossipPort) { + this.gossipPort = gossipPort; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + StorageClusterSettings that = (StorageClusterSettings) o; + + if (cqlPort != that.cqlPort) return false; + if (gossipPort != that.gossipPort) return false; + + return true; + } + + @Override + public int hashCode() { + int result = cqlPort; + result = 29 * result + gossipPort; + return result; + } + + @Override + public String toString() { + return "StorageClusterSettings[cqlPort=" + cqlPort + ", gossipPort=" + gossipPort + "]"; + } +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/ClusterConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/ClusterConfigurationEditor.java new file mode 100644 index 0000000..bd11d03 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/ClusterConfigurationEditor.java @@ -0,0 +1,238 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.admin.storage; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.Overflow; +import com.smartgwt.client.util.BooleanCallback; +import com.smartgwt.client.util.SC; +import com.smartgwt.client.widgets.events.ClickEvent; +import com.smartgwt.client.widgets.events.ClickHandler; +import com.smartgwt.client.widgets.form.fields.FormItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; +import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.form.validator.IsIntegerValidator; +import com.smartgwt.client.widgets.form.validator.Validator; +import com.smartgwt.client.widgets.layout.LayoutSpacer; +import com.smartgwt.client.widgets.toolbar.ToolStrip; + +import org.rhq.core.domain.cloud.StorageClusterSettings; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.RefreshableView; +import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedToolStrip; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; +import org.rhq.enterprise.gui.coregui.client.util.message.Message; + +/** + * The component for editing the cluster wide configuration + * + * @author Jirka Kremser + */ +public class ClusterConfigurationEditor extends EnhancedVLayout implements RefreshableView { + + private EnhancedDynamicForm form; + private EnhancedIButton saveButton; + private boolean oddRow; + private StorageClusterSettings settings; + + private static String FIELD_CQL_PORT = "cql_port"; + private static String FIELD_GOSSIP_PORT = "gossip_port"; + + public ClusterConfigurationEditor() { + super(); + } + + private void fetchClusterSettings() { + GWTServiceLookup.getStorageService().retrieveClusterSettings( + new AsyncCallback<StorageClusterSettings>() { + @Override + public void onFailure(Throwable caught) { + Message message = new Message(MSG.view_configurationHistoryDetails_error_loadFailure(), + Message.Severity.Warning); + } + + @Override + public void onSuccess(StorageClusterSettings settings) { + ClusterConfigurationEditor.this.settings = settings; + prepareForm(); + } + }); + } + + private void save() { + updateSettings(); + GWTServiceLookup.getStorageService().updateClusterSettings(settings, new AsyncCallback<Void>() { + public void onSuccess(Void result) { + Message msg = new Message("Storage node settings were successfully updated.", Message.Severity.Info); + CoreGUI.getMessageCenter().notify(msg); + } + + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("Unable to update the storage node settings.", caught); + } + }); + } + + private List<FormItem> buildOneFormRowWithValidator(String name, String title, String value, String description, + Validator validator) { + return buildOneFormRow(name, title, value, description, false, validator); + } + + private List<FormItem> buildOneFormRow(String name, String title, String value, String description, + boolean unitsDropdown, Validator validator) { + List<FormItem> fields = new ArrayList<FormItem>(); + StaticTextItem nameItem = new StaticTextItem(); + nameItem.setStartRow(true); + nameItem.setValue("<b>" + title + "</b>"); + nameItem.setShowTitle(false); + nameItem.setCellStyle(oddRow ? "OddRow" : "EvenRow"); + fields.add(nameItem); + + FormItem valueItem = null; + valueItem = new TextItem(); + valueItem.setName(name); + valueItem.setValue(value); + valueItem.setWidth(220); + if (validator != null) { + valueItem.setValidators(validator); + } + valueItem.setValidateOnChange(true); + valueItem.setAlign(Alignment.CENTER); + valueItem.setShowTitle(false); + valueItem.setRequired(true); + valueItem.setCellStyle(oddRow ? "OddRow" : "EvenRow"); + fields.add(valueItem); + + StaticTextItem descriptionItem = new StaticTextItem(); + descriptionItem.setValue(description); + descriptionItem.setShowTitle(false); + descriptionItem.setEndRow(true); + descriptionItem.setCellStyle(oddRow ? "OddRow" : "EvenRow"); + fields.add(descriptionItem); + + oddRow = !oddRow; + return fields; + } + + private List<FormItem> buildHeaderItems() { + List<FormItem> fields = new ArrayList<FormItem>(); + fields.add(createHeaderTextItem(MSG.view_configEdit_property())); + fields.add(createHeaderTextItem(MSG.common_title_value())); + fields.add(createHeaderTextItem(MSG.common_title_description())); + return fields; + } + + private StaticTextItem createHeaderTextItem(String value) { + StaticTextItem unsetHeader = new StaticTextItem(); + unsetHeader.setValue(value); + unsetHeader.setShowTitle(false); + unsetHeader.setCellStyle("configurationEditorHeaderCell"); + return unsetHeader; + } + + @Override + protected void onDraw() { + super.onDraw(); + refresh(); + } + + private void prepareForm() { + form = new EnhancedDynamicForm(); + form.setHiliteRequiredFields(true); + form.setNumCols(3); + form.setCellPadding(5); + form.setColWidths(190, 220, "*"); + form.setIsGroup(true); + form.setGroupTitle("Cluster Wide Settings"); + form.setBorder("1px solid #AAA"); + oddRow = true; + + List<FormItem> items = buildHeaderItems(); +// IntegerRangeValidator positiveInteger = new IntegerRangeValidator(); +// positiveInteger.setMin(1); +// positiveInteger.setMax(Integer.MAX_VALUE); + IsIntegerValidator validator = new IsIntegerValidator(); + items.addAll(buildOneFormRowWithValidator(FIELD_CQL_PORT, "CQL Port", String.valueOf(settings.getCqlPort()), + "The port on which the Storage Nodes listens for CQL client connections.", validator)); + +// IntegerRangeValidator portValidator = new IntegerRangeValidator(); +// portValidator.setMin(1); +// portValidator.setMax(65535); // (1 << 16) - 1 + validator = new IsIntegerValidator(); + items.addAll(buildOneFormRowWithValidator(FIELD_GOSSIP_PORT, "Gossip Port", String.valueOf(settings.getGossipPort()), + "The port used for internode communication. This is a shared, cluster-wide setting.", validator)); + form.setFields(items.toArray(new FormItem[items.size()])); + form.setWidth100(); + form.setOverflow(Overflow.VISIBLE); + setWidth100(); + + LayoutSpacer spacer = new LayoutSpacer(); + spacer.setWidth100(); + + ToolStrip toolStrip = buildToolStrip(); + setMembers(form, spacer, toolStrip); + form.validate(); + markForRedraw(); + } + + @Override + public void refresh() { + fetchClusterSettings(); + } + + private EnhancedToolStrip buildToolStrip() { + saveButton = new EnhancedIButton(MSG.common_button_save()); + saveButton.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent clickEvent) { + if (form.validate()) { + SC.ask( + "Changing the cluster wide configuration will eventually affect all the storage nodes. Do you want to continue?", + new BooleanCallback() { + @Override + public void execute(Boolean value) { + if (value) { + save(); + } + } + }); + } + } + }); + EnhancedToolStrip toolStrip = new EnhancedToolStrip(); + toolStrip.setWidth100(); + toolStrip.setMembersMargin(5); + toolStrip.setLayoutMargin(5); + toolStrip.addMember(saveButton); + + return toolStrip; + } + + private StorageClusterSettings updateSettings() { + settings.setCqlPort(Integer.parseInt(form.getValueAsString(FIELD_CQL_PORT))); + settings.setGossipPort(Integer.parseInt(form.getValueAsString(FIELD_GOSSIP_PORT))); + return settings; + } +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java index c99cf70c..d6a91cb 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java @@ -18,26 +18,15 @@ */ package org.rhq.enterprise.gui.coregui.client.admin.storage;
-import java.util.ArrayList; import java.util.EnumSet;
import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.smartgwt.client.data.DataSourceField; -import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.widgets.Label; -import com.smartgwt.client.widgets.grid.CellFormatter; -import com.smartgwt.client.widgets.grid.ListGrid; -import com.smartgwt.client.widgets.grid.ListGridField; -import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
-import org.rhq.core.domain.criteria.AlertCriteria; -import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.resource.ResourceType; -import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; -import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.collection.ArrayUtils; import org.rhq.enterprise.gui.coregui.client.BookmarkableView; import org.rhq.enterprise.gui.coregui.client.CoreGUI; @@ -45,16 +34,10 @@ import org.rhq.enterprise.gui.coregui.client.IconEnum; import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.ViewPath; import org.rhq.enterprise.gui.coregui.client.admin.AdministrationView; -import org.rhq.enterprise.gui.coregui.client.alert.AlertDataSource; -import org.rhq.enterprise.gui.coregui.client.alert.AlertHistoryView; import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTab; import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTabSet; -import org.rhq.enterprise.gui.coregui.client.components.table.Table; -import org.rhq.enterprise.gui.coregui.client.components.view.HasViewName; 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.groups.detail.configuration.GroupResourceConfigurationEditView; -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.util.Log; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; @@ -66,7 +49,7 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message; * * @author Jirka Kremser */ -public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewName,*/ BookmarkableView { +public class StorageNodeAdminView extends EnhancedVLayout implements BookmarkableView {
public static final ViewName VIEW_ID = new ViewName("StorageNodes", MSG.view_adminTopology_storageNodes(), IconEnum.STORAGE_NODE); @@ -74,7 +57,7 @@ public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewNa public static final String VIEW_PATH = AdministrationView.VIEW_ID + "/" + AdministrationView.SECTION_TOPOLOGY_VIEW_ID + "/" + VIEW_ID;
- private static final String GROUP_NAME = "RHQ Storage Nodes"; +// private static final String GROUP_NAME = "RHQ Storage Nodes";
private final NamedTabSet tabset; private TabInfo tableTabInfo = new TabInfo(0, new ViewName("Nodes")); @@ -158,31 +141,36 @@ public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewNa }); } } else if (tabInfo.equals(settingsTabInfo)) { - ResourceGroupCriteria criteria = new ResourceGroupCriteria(); - criteria.addFilterName(GROUP_NAME); - criteria.setStrict(true); - GWTServiceLookup.getResourceGroupService().findResourceGroupCompositesByCriteria(criteria, - new AsyncCallback<PageList<ResourceGroupComposite>>() { - @Override - public void onFailure(Throwable caught) { - Message message = new Message(MSG.view_group_detail_failLoadComp(String.valueOf(GROUP_NAME)), - Message.Severity.Warning); - CoreGUI.goToView(VIEW_ID.getName(), message); - } - - @Override - public void onSuccess(PageList<ResourceGroupComposite> result) { - if (result.isEmpty()) { - onFailure(new Exception("Group with name [" + GROUP_NAME + "] does not exist.")); - } else { - ResourceGroupComposite groupComposite = result.get(0); - loadResourceType(groupComposite.getResourceGroup().getResourceType().getId()); - tabset.getTabByName(tabInfo.name.getName()).setPane( - new GroupResourceConfigurationEditView(groupComposite)); - tabset.selectTab(tabInfo.index); - } - } - }); + ClusterConfigurationEditor editor = new ClusterConfigurationEditor(); + tabset.getTabByName(tabInfo.name.getName()).setPane(editor); + tabset.selectTab(tabInfo.index); + + // we don't group configuration editor anymore +// ResourceGroupCriteria criteria = new ResourceGroupCriteria(); +// criteria.addFilterName(GROUP_NAME); +// criteria.setStrict(true); +// GWTServiceLookup.getResourceGroupService().findResourceGroupCompositesByCriteria(criteria, +// new AsyncCallback<PageList<ResourceGroupComposite>>() { +// @Override +// public void onFailure(Throwable caught) { +// Message message = new Message(MSG.view_group_detail_failLoadComp(String.valueOf(GROUP_NAME)), +// Message.Severity.Warning); +// CoreGUI.goToView(VIEW_ID.getName(), message); +// } +// +// @Override +// public void onSuccess(PageList<ResourceGroupComposite> result) { +// if (result.isEmpty()) { +// onFailure(new Exception("Group with name [" + GROUP_NAME + "] does not exist.")); +// } else { +// ResourceGroupComposite groupComposite = result.get(0); +// loadResourceType(groupComposite.getResourceGroup().getResourceType().getId()); +// tabset.getTabByName(tabInfo.name.getName()).setPane( +// new GroupResourceConfigurationEditView(groupComposite)); +// tabset.selectTab(tabInfo.index); +// } +// } +// }); } }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java index 38829a5..72f17b18 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java @@ -27,6 +27,7 @@ import java.util.Map;
import com.google.gwt.user.client.rpc.RemoteService;
+import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeConfigurationComposite; import org.rhq.core.domain.cloud.StorageNodeLoadComposite; @@ -87,4 +88,8 @@ public interface StorageGWTService extends RemoteService { StorageNodeConfigurationComposite retrieveConfiguration(StorageNode storageNode) throws RuntimeException;
void updateConfiguration(StorageNodeConfigurationComposite storageNodeConfiguration) throws RuntimeException; + + StorageClusterSettings retrieveClusterSettings() throws RuntimeException; + + void updateClusterSettings(StorageClusterSettings clusterSettings) throws RuntimeException; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java index b7437e3..ae18075 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map;
+import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeConfigurationComposite; import org.rhq.core.domain.cloud.StorageNodeLoadComposite; @@ -40,6 +41,7 @@ import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal; import org.rhq.enterprise.server.measurement.util.MeasurementUtils; import org.rhq.enterprise.server.operation.OperationManagerLocal; import org.rhq.enterprise.server.resource.ResourceManagerLocal; +import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
/** @@ -51,6 +53,8 @@ public class StorageGWTServiceImpl extends AbstractGWTServiceImpl implements Sto
private StorageNodeManagerLocal storageNodeManager = LookupUtil.getStorageNodeManager();
+ private StorageClusterSettingsManagerLocal storageClusterSettingsManager = LookupUtil.getStorageClusterSettingsManagerLocal(); + private OperationManagerLocal operationManager = LookupUtil.getOperationManager();
private ResourceManagerLocal resourceManager = LookupUtil.getResourceManager(); @@ -179,4 +183,23 @@ public class StorageGWTServiceImpl extends AbstractGWTServiceImpl implements Sto throw getExceptionToThrowToClient(t); } } + + @Override + public void updateClusterSettings(StorageClusterSettings clusterSettings) throws RuntimeException { + try { + storageClusterSettingsManager.setClusterSettings(getSessionSubject(), clusterSettings); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override + public StorageClusterSettings retrieveClusterSettings() throws RuntimeException { + try { + return SerialUtility.prepare(storageClusterSettingsManager.getClusterSettings(getSessionSubject()), + "StorageGWTServiceImpl.retrieveClusterSettings"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } } diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java index 3ac61e4..c9738a7 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java @@ -3,6 +3,7 @@ package org.rhq.enterprise.server.storage; import javax.ejb.Stateless;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.cloud.StorageClusterSettings;
/** * @author John Sanda diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 861e3fa..5cce984 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -53,6 +53,7 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNode.OperationMode; +import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.cloud.StorageNodeConfigurationComposite; import org.rhq.core.domain.cloud.StorageNodeLoadComposite; import org.rhq.core.domain.common.JobTrigger; @@ -84,7 +85,6 @@ import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.rest.reporting.MeasurementConverter; import org.rhq.enterprise.server.scheduler.SchedulerLocal; -import org.rhq.enterprise.server.storage.StorageClusterSettings; import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerLocal; import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; import org.rhq.enterprise.server.util.CriteriaQueryGenerator; diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettings.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettings.java deleted file mode 100644 index 2098acd..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettings.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.rhq.enterprise.server.storage; - -import java.io.Serializable; - -/** - * @author John Sanda - */ -public class StorageClusterSettings implements Serializable { - - private static final long serialVersionUID = 1; - - private int cqlPort; - - private int gossipPort; - - public int getCqlPort() { - return cqlPort; - } - - public void setCqlPort(int cqlPort) { - this.cqlPort = cqlPort; - } - - public int getGossipPort() { - return gossipPort; - } - - public void setGossipPort(int gossipPort) { - this.gossipPort = gossipPort; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - StorageClusterSettings that = (StorageClusterSettings) o; - - if (cqlPort != that.cqlPort) return false; - if (gossipPort != that.gossipPort) return false; - - return true; - } - - @Override - public int hashCode() { - int result = cqlPort; - result = 29 * result + gossipPort; - return result; - } - - @Override - public String toString() { - return "StorageClusterSettings[cqlPort=" + cqlPort + ", gossipPort=" + gossipPort + "]"; - } -} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java index 9418bca..64fb310 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java @@ -6,8 +6,11 @@ import javax.ejb.EJB; import javax.ejb.Stateless;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.common.composite.SystemSetting; import org.rhq.core.domain.common.composite.SystemSettings; +import org.rhq.enterprise.server.authz.RequiredPermission; import org.rhq.enterprise.server.system.SystemManagerLocal;
/** @@ -20,6 +23,7 @@ public class StorageClusterSettingsManagerBean implements StorageClusterSettings private SystemManagerLocal systemManager;
@Override + @RequiredPermission(Permission.MANAGE_SETTINGS) public StorageClusterSettings getClusterSettings(Subject subject) { SystemSettings settings = systemManager.getSystemSettings(subject); Map<String, String> settingsMap = settings.toMap(); @@ -43,6 +47,7 @@ public class StorageClusterSettingsManagerBean implements StorageClusterSettings }
@Override + @RequiredPermission(Permission.MANAGE_SETTINGS) public void setClusterSettings(Subject subject, StorageClusterSettings clusterSettings) { SystemSettings settings = new SystemSettings(); settings.put(SystemSetting.STORAGE_CQL_PORT, Integer.toString(clusterSettings.getCqlPort())); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java index cb63bc4..f98cccc 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java @@ -3,6 +3,7 @@ package org.rhq.enterprise.server.storage; import javax.ejb.Local;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.cloud.StorageClusterSettings;
/** * @author John Sanda diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index 2a79c59..4969c46 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -17,6 +17,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.cloud.StorageClusterSettings; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.configuration.Configuration; diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java index 5aded7d..3cde894 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java @@ -188,8 +188,10 @@ import org.rhq.enterprise.server.scheduler.SchedulerBean; import org.rhq.enterprise.server.scheduler.SchedulerLocal; import org.rhq.enterprise.server.search.SavedSearchManagerBean; import org.rhq.enterprise.server.search.SavedSearchManagerLocal; -import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; +import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerBean; +import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerLocal; import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerBean; +import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; import org.rhq.enterprise.server.subsystem.AlertSubsystemManagerBean; import org.rhq.enterprise.server.subsystem.AlertSubsystemManagerLocal; import org.rhq.enterprise.server.subsystem.ConfigurationSubsystemManagerBean; @@ -492,6 +494,10 @@ public final class LookupUtil { public static StorageNodeOperationsHandlerLocal getStorageNodeOperationsHandler() { return lookupLocal(StorageNodeOperationsHandlerBean.class); } + + public static StorageClusterSettingsManagerLocal getStorageClusterSettingsManagerLocal() { + return lookupLocal(StorageClusterSettingsManagerBean.class); + }
public static ClusterManagerLocal getClusterManager() { return lookupLocal(ClusterManagerBean.class);
commit dcec800ff2597f4aede87e13927b8ec83f68fee6 Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 16:31:49 2013 -0400
updating api checks
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 08e793c..58bd618 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -65,6 +65,13 @@ </difference>
<difference> + <className>org/rhq/enterprise/server/cloud/StorageNodeManagerRemote</className> + <differenceType>7012</differenceType> <!-- method added to an interface --> + <method>void deployStorageNode(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.cloud.StorageNode)</method> + <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> + </difference> + + <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void assignBundlesToBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method>
commit e2ba1f5cada1f6b4fda5dd1b11fb75f0be1138b0 Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 01:56:04 2013 -0400
add maintenance flag for queueing up storage nodes to be processed
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 9633be5..2c48bbd 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2212,6 +2212,7 @@ </schemaSpec>
<schemaSpec version="2.137"> + <schema-addColumn table="RHQ_STORAGE_NODE" column="MAINTENANCE_PENDING" columnType="BOOLEAN"/> <schema-addColumn table="RHQ_STORAGE_NODE" column="ERROR_MSG" columnType="LONGVARCHAR"/> <schema-addColumn table="RHQ_STORAGE_NODE" column="RESOURCE_OP_HIST_ID" columnType="INTEGER"/> <schema-directSQL> @@ -2221,6 +2222,12 @@ FOREIGN KEY (RESOURCE_OP_HIST_ID) REFERENCES RHQ_OPERATION_HISTORY (ID) </statement> + <statement targetDBVendor="postgresql" desc="Set maintenance_pending flag to false for existing storage nodes"> + UPDATE RHQ_STORAGE_NODE SET IGNORED = false + </statement> + <statement targetDBVendor="oracle" desc="Set maintenance_pending flag to false for existing storage nodes"> + UPDATE RHQ_STORAGE_NODE SET IGNORED = 0 + </statement> </schema-directSQL> </schemaSpec>
commit 9b4f45e77db9a437cdc861359fab77bc8ef2c127 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 23:02:34 2013 -0400
adding more error handling for storage node deployments
In my previous commit I added code to persist resource operation failures that occur during storage node deployment. This commit adds error handling for unexpected server side errors. Errors are logged to the StorageNode entity in a separate transaction to ensure that the error message gets persisted.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java deleted file mode 100644 index fca6e96..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.rhq.enterprise.server.storage; - -/** - * @author John Sanda - */ -public class StorageNodeDeploymentException extends RuntimeException { - - public StorageNodeDeploymentException() { - } - - public StorageNodeDeploymentException(String message) { - super(message); - } - - public StorageNodeDeploymentException(String message, Throwable cause) { - super(message, cause); - } - - public StorageNodeDeploymentException(Throwable cause) { - super(cause); - } -}
commit 414d99725afd354290d44295e00dc8bf1a974025 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 16:13:18 2013 -0400
add fields in StorageNode for error reporting during maintenance
Storage node deployment and undeployment consists of a series of different resource operations. The (un)deployment work flow could fail due to one of those resource operations. When that occurs we can provide a direct link in the StorageNode.failedOperation field to the operation history of the failed operation. This direct link will help with providing quick insight into the cause of the failure.
There is also a new errorMessage field in StorageNode. This field will provide summary info about the failure. If the failure is in server side processing and not in a resource operation, then the errorMessage field should be set but not the failedOperation field.
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 949ca4b..9633be5 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2211,6 +2211,19 @@ </schema-directSQL> </schemaSpec>
+ <schemaSpec version="2.137"> + <schema-addColumn table="RHQ_STORAGE_NODE" column="ERROR_MSG" columnType="LONGVARCHAR"/> + <schema-addColumn table="RHQ_STORAGE_NODE" column="RESOURCE_OP_HIST_ID" columnType="INTEGER"/> + <schema-directSQL> + <statement desc="Creating RHQ_STORAGE_NODE foreign key to RHQ_OPERATION_HISTORY"> + ALTER TABLE RHQ_STORAGE_NODE + ADD CONSTRAINT RHQ_SN_OP_HIST_ID_FK + FOREIGN KEY (RESOURCE_OP_HIST_ID) + REFERENCES RHQ_OPERATION_HISTORY (ID) + </statement> + </schema-directSQL> + </schemaSpec> + </dbupgrade> </target> </project>
commit 7440eb0bd4e594802ee492c86b34e6043186c8f4 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 12:08:13 2013 -0400
refactoring state transitions and adding method for deployment
When a storage node is committed into inventory its operation mode is set to INSTALLED, unless the storage node entity exists in which case the mode is set to NORMAL. After creating the storage node entity, deployment is started. The operation mode changs to ANNOUNCE. The address of the new node is announced to existing cluster nodes. After announcing completes, the operation mode changes to BOOTSTRAP, and the prepareForBootstrap operation is run on the new node. When the new node is reported up as part of the cluster, the operation mode of all cluster modes is set to ADD_NODE_MAINTENANCE. The addNodeMaintenance operation is then run on each storage node. When that operation completes, the node's operation mode is set back to NORMAL.
The StorageNodeManagerBean.deployStorageNode method looks at the operation mode of the node to determine at what step in the process to start the deployment. The deployStorageNode method is the only method that the UI or remote API will need to invoke to start or resume a deployment.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java new file mode 100644 index 0000000..fca6e96 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java @@ -0,0 +1,22 @@ +package org.rhq.enterprise.server.storage; + +/** + * @author John Sanda + */ +public class StorageNodeDeploymentException extends RuntimeException { + + public StorageNodeDeploymentException() { + } + + public StorageNodeDeploymentException(String message) { + super(message); + } + + public StorageNodeDeploymentException(String message, Throwable cause) { + super(message, cause); + } + + public StorageNodeDeploymentException(Throwable cause) { + super(cause); + } +}
commit e696283aacbf34052bce0777af52ac4ee6e1e6bd Author: Stefan Negrea snegrea@redhat.com Date: Wed Aug 14 15:44:07 2013 -0500
Fixing errors after rebase merge.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index cb62d9c..861e3fa 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -153,7 +153,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN private ResourceManagerLocal resourceManager;
@EJB - private StorageClusterSettingsManagerBean storageClusterSettingsManager; + private StorageClusterSettingsManagerLocal storageClusterSettingsManager;
@EJB private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler; @@ -640,7 +640,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
return configuration; } - + @Override @Asynchronous public void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) {
commit a67e1845348543949806de7061b198998c92af27 Author: Stefan Negrea snegrea@redhat.com Date: Wed Aug 14 14:37:26 2013 -0500
[BZ 991598] Add basica node configuration validation to the composite class. It validates heap settings as well as port settings.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 35eec41..cb62d9c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -153,7 +153,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN private ResourceManagerLocal resourceManager;
@EJB - private StorageClusterSettingsManagerLocal storageClusterSettingsManager; + private StorageClusterSettingsManagerBean storageClusterSettingsManager;
@EJB private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler; @@ -590,7 +590,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
@Override public Integer[] findResourcesWithAlertDefinitions(StorageNode storageNode) { - List<StorageNode> initialStorageNodes = null; + List<StorageNode> initialStorageNodes = getStorageNodes(); if (storageNode == null) { initialStorageNodes = getStorageNodes(); } else { @@ -640,7 +640,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
return configuration; } - + @Override @Asynchronous public void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) {
commit 159290206de43cdb6bac84fd4424cad7f8b31e05 Author: jfclere jfclere@neo2.gva.redhat.com Date: Mon Apr 15 17:07:28 2013 +0200
[BZ 865460] Cannot add a Group to tomcat's UserDatabase
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java index 0a95069..ead4956 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java @@ -51,6 +51,7 @@ public class TomcatUserDatabaseComponent extends MBeanResourceComponent<TomcatSe if (TomcatGroupComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) { name = report.getResourceConfiguration().getSimple("groupname").getStringValue(); newRoles = report.getResourceConfiguration().getSimple(TomcatGroupComponent.CONFIG_ROLES); + report.getResourceConfiguration().remove(TomcatGroupComponent.CONFIG_ROLES); objectName = String.format("Users:type=Group,groupname="%s",database=UserDatabase", name); operation = "createGroup"; } else if (TomcatRoleComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) {
commit 1d7cd37a18df200b7ce9205da2565d46a8ea665c Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:22:52 2013 +0200
[BZ 921261] WebModule is reported as DOWN or UNAVAILABLE ... from 00e594847fe67da46f8976df58b5d2324d6ebb48
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java index 2a39e25..0a51c45 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java @@ -370,7 +370,23 @@ public class TomcatWarComponent extends MBeanResourceComponent<TomcatVHostCompon mbeanOperation.invoke(paramValues);
if (!WarOperation.DESTROY.equals(operation)) { - String state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); + String state = null; + try { + // check to see if the mbean is truly active + state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); + } catch (Exception e) { + // if not active an exception may be thrown + state = WarMBeanState.STOPPED; + // try "state" for Tomcat 5.5 + try { + int stateInt = (Integer) this.webModuleMBean.getAttribute("state").refresh(); + if (stateInt == 1) { + state = WarMBeanState.STARTED; + } + } catch (Exception ex) { + // Ignore + } + } String expectedState = getExpectedPostExecutionState(operation); if (!state.equals(expectedState)) { throw new Exception("Failed to " + name + " webapp (value of the 'state' attribute of MBean '"
commit eade99f427f742c2eac5a9e4da0636a52da07cbb Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:17:22 2013 +0200
[BZ 921194] Connectors are not properly discovered and therefore are unavailable.. from 00e594847fe67da46f8976df58b5d2324d6ebb48.
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java index 7a65a73..32566d5 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java @@ -132,12 +132,14 @@ public class TomcatConnectorDiscoveryComponent extends MBeanResourceDiscoveryCom if (connectorON != null) { EmsBean connectorBean = connection.getBean(connectorON); EmsAttribute executorNameAttrib = connectorBean.getAttribute("executorName"); - Object executorNameValue = executorNameAttrib.getValue(); - if (executorNameValue != null) { - String executorName = executorNameValue.toString(); - if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { - pluginConfiguration.put(new PropertySimple( - TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); + if (executorNameAttrib != null) { + Object executorNameValue = executorNameAttrib.getValue(); + if (executorNameValue != null) { + String executorName = executorNameValue.toString(); + if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { + pluginConfiguration.put(new PropertySimple( + TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); + } } } }
commit b633b97c60a2b50ad292a8ba7d19e2e6cb351d34 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:13:02 2013 +0200
Fix BZ 865460 from 417fbb59817edf64a93d3cca00f2c51926379ab2
Conflicts:
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java index ead4956..0a95069 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java @@ -51,7 +51,6 @@ public class TomcatUserDatabaseComponent extends MBeanResourceComponent<TomcatSe if (TomcatGroupComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) { name = report.getResourceConfiguration().getSimple("groupname").getStringValue(); newRoles = report.getResourceConfiguration().getSimple(TomcatGroupComponent.CONFIG_ROLES); - report.getResourceConfiguration().remove(TomcatGroupComponent.CONFIG_ROLES); objectName = String.format("Users:type=Group,groupname="%s",database=UserDatabase", name); operation = "createGroup"; } else if (TomcatRoleComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) {
commit cf3da14deebde03857ad582f0da93763093151a4 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 14:33:38 2013 +0200
fix for BZ: 707349 from e7d48240474fba87f1a3c4118de4618fd2c8b32d.
Conflicts:
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java index 32566d5..7a65a73 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java @@ -132,14 +132,12 @@ public class TomcatConnectorDiscoveryComponent extends MBeanResourceDiscoveryCom if (connectorON != null) { EmsBean connectorBean = connection.getBean(connectorON); EmsAttribute executorNameAttrib = connectorBean.getAttribute("executorName"); - if (executorNameAttrib != null) { - Object executorNameValue = executorNameAttrib.getValue(); - if (executorNameValue != null) { - String executorName = executorNameValue.toString(); - if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { - pluginConfiguration.put(new PropertySimple( - TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); - } + Object executorNameValue = executorNameAttrib.getValue(); + if (executorNameValue != null) { + String executorName = executorNameValue.toString(); + if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { + pluginConfiguration.put(new PropertySimple( + TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); } } } diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java index 0a51c45..2a39e25 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java @@ -370,23 +370,7 @@ public class TomcatWarComponent extends MBeanResourceComponent<TomcatVHostCompon mbeanOperation.invoke(paramValues);
if (!WarOperation.DESTROY.equals(operation)) { - String state = null; - try { - // check to see if the mbean is truly active - state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); - } catch (Exception e) { - // if not active an exception may be thrown - state = WarMBeanState.STOPPED; - // try "state" for Tomcat 5.5 - try { - int stateInt = (Integer) this.webModuleMBean.getAttribute("state").refresh(); - if (stateInt == 1) { - state = WarMBeanState.STARTED; - } - } catch (Exception ex) { - // Ignore - } - } + String state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); String expectedState = getExpectedPostExecutionState(operation); if (!state.equals(expectedState)) { throw new Exception("Failed to " + name + " webapp (value of the 'state' attribute of MBean '"
commit 0047c728371fd9ce2a9719792e226f4f6d122247 Author: Jirka Kremser jkremser@redhat.com Date: Wed Aug 14 19:19:52 2013 +0200
Alert view for a single storage node and its child resources.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 861e3fa..35eec41 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -590,7 +590,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
@Override public Integer[] findResourcesWithAlertDefinitions(StorageNode storageNode) { - List<StorageNode> initialStorageNodes = getStorageNodes(); + List<StorageNode> initialStorageNodes = null; if (storageNode == null) { initialStorageNodes = getStorageNodes(); } else {
commit a10b2e819d6a0ad331c7c8de8b6f2ba79629415e Author: Jay Shaughnessy jshaughn@redhat.com Date: Wed Aug 14 11:20:02 2013 -0400
remove entries for stuff still in a branch
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 52770ff..08e793c 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -74,7 +74,7 @@ <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> + <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, java.lang.String, java.lang.String)</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
@@ -169,11 +169,4 @@ <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
- <difference> - <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> - <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>org.rhq.core.domain.bundle.BundleGroup updateBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> - <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> - </difference> - </differences>
commit 8e8062449a5b1ac7e0814724c2232c018e93022c Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 13 15:01:50 2013 -0400
fix some issues, add some new api methods
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 08e793c..52770ff 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -74,7 +74,7 @@ <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, java.lang.String, java.lang.String)</method> + <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
@@ -169,4 +169,11 @@ <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
+ <difference> + <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> + <differenceType>7012</differenceType> <!-- method added to an interface --> + <method>org.rhq.core.domain.bundle.BundleGroup updateBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> + <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> + </difference> + </differences>
commit 2807c04d36735ed07af9000ac646340775ab94b0 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 20 11:49:30 2013 -0400
get button enablement working for bundles list view using the various permission schemes - add some new authz mgr bean support for bundle perms - fix the newly added permissions filter in RoleCriteria - add BundleAuthorizedTableAction and RoleAuthorizedTableAction -
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/auth/Subject.java b/modules/core/domain/src/main/java/org/rhq/core/domain/auth/Subject.java index c70d651..12fb916 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/auth/Subject.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/auth/Subject.java @@ -211,6 +211,17 @@ import org.rhq.core.domain.resource.group.ResourceGroup; + "FROM Subject s, IN (s.roles) r, IN (r.permissions) p, IN (r.resourceGroups) g, IN (g.implicitResources) res " + "WHERE s = :subject AND p = :permission AND res.inventoryStatus = 'COMMITTED'"),
+ /* + * No easy way to test whether ALL bundles are in some bundle group in some role in some subject where + * subject.id = <id> & role.permission = <perm> + * + * Instead, we must use this potentially VERY costly query (costly because the result list could be huge in large + * environments). However, we can return bundle.id only, to save a lot of traffic across the line and speed it up. + */ + @NamedQuery(name = Subject.QUERY_GET_BUNDLES_BY_PERMISSION, query = "SELECT distinct bundle.id " + + "FROM Subject s, IN (s.roles) r, IN (r.permissions) p, IN (r.bundleGroups) g, IN (g.bundles) bundle " + + "WHERE s = :subject AND p = :permission"), + @NamedQuery(name = Subject.QUERY_FIND_AVAILABLE_SUBJECTS_FOR_ROLE_WITH_EXCLUDES, query = "" // + "SELECT DISTINCT s " + " FROM Subject AS s LEFT JOIN s.roles AS r " // + " WHERE s.id NOT IN " // @@ -263,6 +274,7 @@ public class Subject implements Serializable { public static final String QUERY_CAN_VIEW_BUNDLE = "Subject.canViewBundle"; public static final String QUERY_CAN_VIEW_BUNDLE_GROUP = "Subject.canViewBundleGroup";
+ public static final String QUERY_GET_BUNDLES_BY_PERMISSION = "Subject.getBundlesByPermission"; public static final String QUERY_GET_RESOURCES_BY_PERMISSION = "Subject.getResourcesByPermission";
public static final String QUERY_FIND_AVAILABLE_SUBJECTS_FOR_ROLE_WITH_EXCLUDES = "Subject.findAvailableSubjectsForRoleWithExcludes"; diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java index b44f62d..e68df50 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java @@ -57,21 +57,21 @@ public class RoleCriteria extends Criteria {
public RoleCriteria() { filterOverrides.put("subjectId", "" // - + "id IN ( SELECT innerRole.id " // - + " FROM Role innerRole " // - + " JOIN innerRole.subjects innerSubject " // - + " WHERE innerSubject.id = ? )"); + + "id IN ( SELECT innerRole1.id " // + + " FROM Role innerRole1 " // + + " JOIN innerRole1.subjects innerSubject1 " // + + " WHERE innerSubject1.id = ? )");
filterOverrides.put("ldapSubjectId", "" // - + "id IN ( SELECT innerRole.id " // - + " FROM Role innerRole " // - + " JOIN innerRole.ldapSubjects innerSubject " // - + " WHERE innerSubject.id = ? )"); + + "id IN ( SELECT innerRole2.id " // + + " FROM Role innerRole2 " // + + " JOIN innerRole2.ldapSubjects innerSubject2 " // + + " WHERE innerSubject2.id = ? )");
filterOverrides.put("permissions", "" // - + "id IN ( SELECT innerRole.id " // - + " FROM Role innerRole " // - + " JOIN irole.permissions perm " // + + "id IN ( SELECT innerRole3.id " // + + " FROM Role innerRole3 " // + + " JOIN innerRole3.permissions perm " // + " WHERE perm IN ( ? ) )"); }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java index 756e4f7..ad66e49 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java @@ -19,10 +19,13 @@ package org.rhq.enterprise.gui.coregui.client.bundle.list;
import java.util.ArrayList; +import java.util.Collection; +import java.util.List; import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Criteria; +import com.smartgwt.client.data.Record; import com.smartgwt.client.types.Alignment; import com.smartgwt.client.types.ListGridFieldType; import com.smartgwt.client.widgets.events.DoubleClickEvent; @@ -42,7 +45,9 @@ import org.rhq.enterprise.gui.coregui.client.IconEnum; import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.bundle.create.BundleCreateWizard; import org.rhq.enterprise.gui.coregui.client.bundle.deploy.BundleDeployWizard; -import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction; +import org.rhq.enterprise.gui.coregui.client.components.table.BundleAuthorizedTableAction; +import org.rhq.enterprise.gui.coregui.client.components.table.RecordExtractor; +import org.rhq.enterprise.gui.coregui.client.components.table.RoleAuthorizedTableAction; import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement; import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; @@ -61,7 +66,7 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity; */ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> {
- private final Set<Permission> permissions; + private final Set<Permission> globalPermissions;
/** * Creates a new list view. @@ -74,7 +79,7 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> {
public BundlesListView(Criteria criteria, Set<Permission> perms) { super(MSG.common_title_bundles(), criteria, IconEnum.BUNDLE.getIcon24x24Path()); - this.permissions = perms; + this.globalPermissions = perms; setDataSource(new BundlesWithLatestVersionDataSource()); }
@@ -129,63 +134,72 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> { });
// only show the buttons if we were given a set of permissions - passing in null is a way to say you only want the list, no actions - if (this.permissions != null) { + if (this.globalPermissions != null) { + boolean hasGlobalDelete = globalPermissions.contains(Permission.DELETE_BUNDLES);
- // TODO NEW BUNDLE ENABLEMENT - // boolean hasAuth = permissions.contains(Permission._BUNDLE); - boolean hasAuth = true; + addTableAction(MSG.common_button_new(), null, new RoleAuthorizedTableAction(BundlesListView.this, + Permission.CREATE_BUNDLES, Permission.CREATE_BUNDLES_IN_GROUP) {
- addTableAction(MSG.common_button_new(), null, new AbstractTableAction( - (hasAuth) ? TableActionEnablement.ALWAYS : TableActionEnablement.NEVER) { public void executeAction(ListGridRecord[] selection, Object actionValue) { - new BundleCreateWizard(permissions).startWizard(); + new BundleCreateWizard(globalPermissions).startWizard(); // we can refresh the table buttons immediately since the wizard is a dialog, the // user can't access enabled buttons anyway. BundlesListView.this.refreshTableInfo(); } });
- addTableAction(MSG.common_button_delete(), MSG.view_bundle_list_deleteConfirm(), new AbstractTableAction( - (hasAuth) ? TableActionEnablement.ANY : TableActionEnablement.NEVER) { - public void executeAction(ListGridRecord[] selections, Object actionValue) { - if (selections == null || selections.length == 0) { - return; - } - - BundlesWithLatestVersionDataSource ds = (BundlesWithLatestVersionDataSource) getDataSource(); - final ArrayList<String> doomedNames = new ArrayList<String>(selections.length); - int[] doomedIds = new int[selections.length]; - int i = 0; - for (ListGridRecord selection : selections) { - BundleWithLatestVersionComposite object = ds.copyValues(selection); - doomedNames.add(object.getBundleName()); - doomedIds[i++] = object.getBundleId(); - } + addTableAction(MSG.common_button_delete(), MSG.view_bundle_list_deleteConfirm(), + new BundleAuthorizedTableAction(BundlesListView.this, TableActionEnablement.ANY, + (hasGlobalDelete ? null : Permission.DELETE_BUNDLES_FROM_GROUP), new RecordExtractor<Integer>() { + public Collection<Integer> extract(Record[] records) { + List<Integer> result = new ArrayList<Integer>(records.length); + for (Record record : records) { + result.add(record.getAttributeAsInt("id")); + } + return result; + } + }) {
- BundleGWTServiceAsync bundleManager = GWTServiceLookup.getBundleService(); - bundleManager.deleteBundles(doomedIds, new AsyncCallback<Void>() { - public void onFailure(Throwable caught) { - String names = doomedNames.toString(); - String error = ErrorHandler.getAllMessages(caught); - Message m = new Message(MSG.view_bundle_list_deletesFailure(), names + "<br/>\n" + error, - Severity.Error); - CoreGUI.getMessageCenter().notify(m); + public void executeAction(ListGridRecord[] selections, Object actionValue) { + if (selections == null || selections.length == 0) { + return; }
- public void onSuccess(Void result) { - Message m = new Message(MSG.view_bundle_list_deletesSuccessful(), doomedNames.toString(), - Severity.Info); - CoreGUI.getMessageCenter().notify(m); - CoreGUI.refresh(); + BundlesWithLatestVersionDataSource ds = (BundlesWithLatestVersionDataSource) getDataSource(); + final ArrayList<String> doomedNames = new ArrayList<String>(selections.length); + int[] doomedIds = new int[selections.length]; + int i = 0; + for (ListGridRecord selection : selections) { + BundleWithLatestVersionComposite object = ds.copyValues(selection); + doomedNames.add(object.getBundleName()); + doomedIds[i++] = object.getBundleId(); } - }); - } - }); + + BundleGWTServiceAsync bundleManager = GWTServiceLookup.getBundleService(); + bundleManager.deleteBundles(doomedIds, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + String names = doomedNames.toString(); + String error = ErrorHandler.getAllMessages(caught); + Message m = new Message(MSG.view_bundle_list_deletesFailure(), names + "<br/>\n" + + error, Severity.Error); + CoreGUI.getMessageCenter().notify(m); + } + + public void onSuccess(Void result) { + Message m = new Message(MSG.view_bundle_list_deletesSuccessful(), doomedNames + .toString(), Severity.Info); + CoreGUI.getMessageCenter().notify(m); + CoreGUI.refresh(); + } + }); + } + });
// can change this back to SINGLE selection when we feel like it. currently allowing the wizard to // select the bundle. - addTableAction(MSG.view_bundle_deploy(), null, new AbstractTableAction( - (hasAuth) ? TableActionEnablement.ALWAYS : TableActionEnablement.NEVER) { + addTableAction(MSG.view_bundle_deploy(), null, new RoleAuthorizedTableAction(BundlesListView.this, + Permission.DEPLOY_BUNDLES, Permission.DEPLOY_BUNDLES_TO_GROUP) { + public void executeAction(ListGridRecord[] selection, Object actionValue) { if (selection.length == 0) { new BundleDeployWizard().startWizard(); @@ -222,6 +236,5 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> { } }); } - } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/AuthorizedTableAction.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/AuthorizedTableAction.java index 7b51bc7..d21fc70 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/AuthorizedTableAction.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/AuthorizedTableAction.java @@ -56,8 +56,8 @@ public abstract class AuthorizedTableAction extends AbstractTableAction { case GLOBAL: globalPermissions.add(p); break; - case RESOURCE: - throw new IllegalArgumentException("Does not support Resource permissions"); + default: + throw new IllegalArgumentException("Does not support non-global permissions"); } }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/BundleAuthorizedTableAction.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/BundleAuthorizedTableAction.java new file mode 100644 index 0000000..2da610a --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/BundleAuthorizedTableAction.java @@ -0,0 +1,125 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.gui.coregui.client.components.table; + +import java.util.Collection; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.widgets.grid.ListGridRecord; + +import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.authz.Permission.Target; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; + +/** + * This class allows for TableAction (ie. Button) enablement based on row selection and bundle perm authorization + * on the selected rows. If possible it is recommended that the table be built using composites that include the + * bundle permission information already, as performance will be better. This approach will require an async + * authz call to the server on each refresh of the TableActions (i.e. each time selection changes in the Table). + * + * For Global Perm authorization see {@link AuthorizedTableAction}. + * + * @author Jay Shaughnessy + */ +public abstract class BundleAuthorizedTableAction extends AbstractTableAction { + + private Table<?> table; + private Permission requiredPermission; + private RecordExtractor<Integer> extractor; + private Collection<Integer> authorizedBundleIds; + + private Boolean isAuthorized; + + /** + * @param table + * @param enablement + * @param requiredPermission if null no check is performed and authorization always passes + * @param extractor + */ + protected BundleAuthorizedTableAction(Table<?> table, Permission requiredPermission, + RecordExtractor<Integer> extractor) { + this(table, TableActionEnablement.ALWAYS, requiredPermission, extractor); + } + + /** + * @param table + * @param enablement + * @param requiredPermission if null no check is performed and authorization always passes + * @param extractor + */ + protected BundleAuthorizedTableAction(Table<?> table, TableActionEnablement enablement, + Permission requiredPermission, RecordExtractor<Integer> extractor) { + super(enablement); + + this.table = table; + this.requiredPermission = requiredPermission; + this.extractor = extractor; + + if (null != this.requiredPermission && Target.BUNDLE != this.requiredPermission.getTarget()) { + throw new IllegalArgumentException("Does not support Global permission"); + } + } + + @Override + public boolean isEnabled(ListGridRecord[] selection) { + // first make sure row selection enablement passes + if (!super.isEnabled(selection)) { + return false; + } + + // if there is no required permission then no check is performed + if (null == requiredPermission) { + return true; + } + + final Collection<Integer> selectedBundleIds = extractor.extract(selection); + boolean isNewSelection = !selectedBundleIds.equals(this.authorizedBundleIds); + + if (isNewSelection) { + isAuthorized = false; + authorizedBundleIds = selectedBundleIds; + } else { + return isAuthorized; + } + + // kick off the async auth check. return false initially and update when the async call returns + + GWTServiceLookup.getAuthorizationService().hasBundlePermission(requiredPermission, selectedBundleIds, + new AsyncCallback<Boolean>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("", caught); + } + + public void onSuccess(Boolean result) { + boolean isStale = !selectedBundleIds.equals(authorizedBundleIds); + if (isStale) { + return; + } + + isAuthorized = result; + table.refreshTableInfo(); + } + + }); + + return isAuthorized; + } +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/RoleAuthorizedTableAction.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/RoleAuthorizedTableAction.java new file mode 100644 index 0000000..497631c --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/RoleAuthorizedTableAction.java @@ -0,0 +1,85 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +package org.rhq.enterprise.gui.coregui.client.components.table; + +import java.util.Arrays; +import java.util.List; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.widgets.grid.ListGridRecord; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.authz.Role; +import org.rhq.core.domain.criteria.RoleCriteria; +import org.rhq.core.domain.util.PageList; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.UserSessionManager; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; + +/** + * This is used only to determine enablement of certain bundle buttons (new, deploy). It activates the button if the user + * has any role with the specified permissions. It requires only one async call and then uses the cached value. + * + * For strict Global Perm authorization see {@link AuthorizedTableAction}. + * + * @author Jay Shaughnessy + */ +public abstract class RoleAuthorizedTableAction extends AbstractTableAction { + + private Table<?> table; + List<Permission> permissions; + private Boolean isAuthorized; + + protected RoleAuthorizedTableAction(Table<?> table, Permission... permissions) { + this.table = table; + this.permissions = Arrays.asList(permissions); + } + + @Override + public boolean isEnabled(ListGridRecord[] selection) { + // first make sure row selection enablement passes + if (!super.isEnabled(selection)) { + return false; + } + + if (null != isAuthorized) { + return isAuthorized.booleanValue(); + } + + // kick off the async auth check. return false initially and update when the async call returns + RoleCriteria criteria = new RoleCriteria(); + Subject subject = UserSessionManager.getSessionSubject(); + criteria.addFilterSubjectId(subject.getId()); + criteria.addFilterPermissions(permissions); + GWTServiceLookup.getRoleService().findRolesByCriteria(criteria, new AsyncCallback<PageList<Role>>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError("", caught); + } + + public void onSuccess(PageList<Role> result) { + isAuthorized = !result.isEmpty(); + table.refreshTableInfo(); + } + }); + + return false; + } +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AuthorizationGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AuthorizationGWTService.java index fdcd01d..2af16c3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AuthorizationGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/AuthorizationGWTService.java @@ -86,4 +86,17 @@ public interface AuthorizationGWTService extends RemoteService { */ boolean hasResourcePermission(Permission permission, Collection<Integer> resourceIds) throws RuntimeException;
+ /** + * Returns true if the current user possesses either: 1) the specified bundle permission for *all* of the + * specified bundles, or 2) is a system superuser which, by definition, gives full access to all bundles + * NOTE: The size of the collection must be less than or equal to 1000 (due to an Oracle limitation). + * + * @param subject the current subject or caller + * @param permission a resource permission (i.e. permission.getTarget() == Permission.Target.RESOURCE) + * @param bundleIds the ids of some Bundles to check permissions against (size of collection must be <= 1000) + * + * @return true if the current user possesses the specified resource permission for the specified resource + */ + boolean hasBundlePermission(Permission permission, Collection<Integer> bundleIds); + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AuthorizationGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AuthorizationGWTServiceImpl.java index 4be6eb9..9dc365f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AuthorizationGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/AuthorizationGWTServiceImpl.java @@ -39,8 +39,9 @@ public class AuthorizationGWTServiceImpl extends AbstractGWTServiceImpl implemen
public Set<Permission> getExplicitResourcePermissions(int resourceId) throws RuntimeException { try { - return SerialUtility.prepare(new HashSet<Permission>(authorizationManager.getExplicitResourcePermissions( - getSessionSubject(), resourceId)), "AuthorizationManager.getExplicitResourcePermissions"); + return SerialUtility.prepare( + new HashSet<Permission>(authorizationManager.getExplicitResourcePermissions(getSessionSubject(), + resourceId)), "AuthorizationManager.getExplicitResourcePermissions"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } @@ -48,8 +49,9 @@ public class AuthorizationGWTServiceImpl extends AbstractGWTServiceImpl implemen
public Set<Permission> getImplicitResourcePermissions(int resourceId) throws RuntimeException { try { - return SerialUtility.prepare(new HashSet<Permission>(authorizationManager.getImplicitResourcePermissions( - getSessionSubject(), resourceId)), "AuthorizationManager.getImplicitResourcePermissions"); + return SerialUtility.prepare( + new HashSet<Permission>(authorizationManager.getImplicitResourcePermissions(getSessionSubject(), + resourceId)), "AuthorizationManager.getImplicitResourcePermissions"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } @@ -57,8 +59,10 @@ public class AuthorizationGWTServiceImpl extends AbstractGWTServiceImpl implemen
public Set<Permission> getExplicitGroupPermissions(int groupId) throws RuntimeException { try { - return SerialUtility.prepare(new HashSet<Permission>(authorizationManager.getExplicitGroupPermissions( - getSessionSubject(), groupId)), "AuthorizationManager.getExplicitGroupPermissions"); + return SerialUtility + .prepare( + new HashSet<Permission>(authorizationManager.getExplicitGroupPermissions(getSessionSubject(), + groupId)), "AuthorizationManager.getExplicitGroupPermissions"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } @@ -66,8 +70,10 @@ public class AuthorizationGWTServiceImpl extends AbstractGWTServiceImpl implemen
public Set<Permission> getImplicitGroupPermissions(int groupId) throws RuntimeException { try { - return SerialUtility.prepare(new HashSet<Permission>(authorizationManager.getImplicitGroupPermissions( - getSessionSubject(), groupId)), "AuthorizationManager.getImplicitGroupPermissions"); + return SerialUtility + .prepare( + new HashSet<Permission>(authorizationManager.getImplicitGroupPermissions(getSessionSubject(), + groupId)), "AuthorizationManager.getImplicitGroupPermissions"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } @@ -75,15 +81,16 @@ public class AuthorizationGWTServiceImpl extends AbstractGWTServiceImpl implemen
public Set<Permission> getExplicitGlobalPermissions() throws RuntimeException { try { - return SerialUtility.prepare(new HashSet<Permission>(authorizationManager - .getExplicitGlobalPermissions(getSessionSubject())), + return SerialUtility.prepare( + new HashSet<Permission>(authorizationManager.getExplicitGlobalPermissions(getSessionSubject())), "AuthorizationManager.getExplicitGlobalPermissions"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } }
- public boolean hasResourcePermission(Permission permission, Collection<Integer> resourceIds) throws RuntimeException { + public boolean hasResourcePermission(Permission permission, Collection<Integer> resourceIds) + throws RuntimeException { try { boolean result = authorizationManager.hasResourcePermission(getSessionSubject(), permission, resourceIds); return result; @@ -92,4 +99,12 @@ public class AuthorizationGWTServiceImpl extends AbstractGWTServiceImpl implemen } }
+ public boolean hasBundlePermission(Permission permission, Collection<Integer> bundleIds) throws RuntimeException { + try { + boolean result = authorizationManager.hasBundlePermission(getSessionSubject(), permission, bundleIds); + return result; + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerBean.java index d5746d3..8464133 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerBean.java @@ -203,6 +203,21 @@ public class AuthorizationManagerBean implements AuthorizationManagerLocal { return (count != 0); }
+ @Override + @SuppressWarnings("unchecked") + public boolean hasBundlePermission(Subject subject, Permission permission, Collection<Integer> bundleIds) { + if (isSystemSuperuser(subject)) { + return true; + } + + Query query = entityManager.createNamedQuery(Subject.QUERY_GET_BUNDLES_BY_PERMISSION); + query.setParameter("subject", subject); + query.setParameter("permission", permission); + + List<Integer> results = query.getResultList(); + return results.containsAll(bundleIds); + } + @SuppressWarnings("unchecked") @Override public boolean hasBundleGroupPermission(Subject subject, Permission permission, int bundleGroupId) { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerLocal.java index 62d3c0c..18003fb 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/AuthorizationManagerLocal.java @@ -168,6 +168,19 @@ public interface AuthorizationManagerLocal { boolean hasBundlePermission(Subject subject, Permission permission, int bundleId);
/** + * Returns true if the current user possesses either: 1) the specified bundle permission for *all* of the + * specified bundles, or 2) is a system superuser which, by definition, gives full access to all bundles + * NOTE: The size of the collection must be less than or equal to 1000 (due to an Oracle limitation). + * + * @param subject the current subject or caller + * @param permission a resource permission (i.e. permission.getTarget() == Permission.Target.RESOURCE) + * @param bundleIds the ids of some Bundles to check permissions against (size of collection must be <= 1000) + * + * @return true if the current user possesses the specified resource permission for the specified resource + */ + boolean hasBundlePermission(Subject subject, Permission permission, Collection<Integer> bundleIds); + + /** * Returns true if the current user possesses the specified bundle permission for the specified bundle group. * * @param subject the current subject or caller
commit 5f567aed7720e20b98bdf5e8fd0abbdc2fdcc956 Author: Jay Shaughnessy jshaughn@redhat.com Date: Mon Aug 19 16:09:31 2013 -0400
Fix non-global bundle create workflow using the "token" approach - move BundleNotFoundException to domain so we have a good ApplicationException to use that is also recognized in the GUI. - add radio button form to bundleGroups wizard step (needs a lot of TLC still) - temporarily fix New bundle button authz, remove MANAGE_BUNDLE
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleNotFoundException.java b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleNotFoundException.java new file mode 100644 index 0000000..803412e --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleNotFoundException.java @@ -0,0 +1,49 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.core.domain.bundle; + +import javax.ejb.ApplicationException; + +/** + * Indicates a required RHQ bundle did not exist. This class is defined in the in the domain module instead + * of the server/jar module because it needs to be accessible by the UI. Note that this is an ApplicationException + * and when throwing this from an EJB it will not be wrapped as an EJBException, and as annotated, it will not rollback + * an ongoing transaction. + */ +@ApplicationException(rollback = false, inherited = true) +public class BundleNotFoundException extends RuntimeException { + private static final long serialVersionUID = 1L; + + // Default no-arg constructor required by JAXB + public BundleNotFoundException() { + } + + /** + * Create an exception indicating the resource with the specified id was not found. + * + * @param bundleId a bundle id + */ + public BundleNotFoundException(int bundleId) { + super("A Bundle with id " + bundleId + " does not exist."); + } + + public BundleNotFoundException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java index 2d6ebbc..e330e3f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java @@ -128,6 +128,7 @@ public class BundleGroupsStep extends AbstractWizardStep {
formItems.add(radioGroupItem); formItems.add(new SpacerItem()); + radioForm.setItems(formItems.toArray(new FormItem[formItems.size()])); canvas.addMember(radioForm);
// go get the assignable/assigned bundle groups for this new bundle version, initial or not diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java index 9344fb6..3e19936 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java @@ -37,6 +37,7 @@ import com.smartgwt.client.widgets.form.fields.TextItem; import com.smartgwt.client.widgets.form.fields.events.ClickEvent; import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
+import org.rhq.core.domain.bundle.BundleNotFoundException; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.core.domain.criteria.BundleVersionCriteria; @@ -281,8 +282,8 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { @Override public void onFailure(Throwable caught) { // This signals that the bundle does not yet exist - if (caught instanceof IllegalStateException) { - handleIllegalStateException((IllegalStateException) caught); + if (caught instanceof BundleNotFoundException) { + handleBundleNotFoundException((BundleNotFoundException) caught);
} else { // Escape it, since it contains the URL, which the user entered. @@ -296,10 +297,10 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { }); }
- private void handleIllegalStateException(IllegalStateException e) { + private void handleBundleNotFoundException(BundleNotFoundException e) { String token = e.getMessage(); if (null == token || token.isEmpty()) { - wizard.getView().showMessage("IllegalStateException: Unexpected failure creating bundle version."); + wizard.getView().showMessage("BundleNotFound: Unexpected failure creating bundle version."); CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), e); wizard.setBundleVersion(null); setButtonsDisableMode(false); @@ -361,7 +362,8 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { } }); } else if (null != uploadDistroForm.getCreateInitialBundleVersionToken()) { - handleIllegalStateException(new IllegalStateException(uploadDistroForm.getCreateInitialBundleVersionToken())); + handleBundleNotFoundException(new BundleNotFoundException( + uploadDistroForm.getCreateInitialBundleVersionToken()));
} else { String errorMessage = uploadDistroForm.getUploadError(); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java index 296a070..756e4f7 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java @@ -131,7 +131,9 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> { // only show the buttons if we were given a set of permissions - passing in null is a way to say you only want the list, no actions if (this.permissions != null) {
- boolean hasAuth = permissions.contains(Permission.MANAGE_BUNDLE); + // TODO NEW BUNDLE ENABLEMENT + // boolean hasAuth = permissions.contains(Permission._BUNDLE); + boolean hasAuth = true;
addTableAction(MSG.common_button_new(), null, new AbstractTableAction( (hasAuth) ? TableActionEnablement.ALWAYS : TableActionEnablement.NEVER) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java index 04fcbf0..e57b852 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java @@ -46,7 +46,7 @@ public class BundleDistributionFileUploadForm extends FileUploadForm {
/** * If this component uploaded a bundle distribution file but failed to create the bundle version - * due to an IllegalStateException (signaling bundle not found), this will return the token necessary to then call + * due to a BundleNotFoundException, this will return the token necessary to then call * createInitialBundleVersionViaToken(). Otherwise, null is returned. * * @return the token required for a a subsequent call to createInitialBundleVersionViaToken(). @@ -63,16 +63,16 @@ public class BundleDistributionFileUploadForm extends FileUploadForm { private int parseResponse(String results) { // the upload servlet will respond with "BundleNotFoundException [createInitialBundleVersionToken]" to indicate // that the BV create failed because the bundle does not yet exist. - String IllegalStateMsgPrefix = "IllegalStateException ["; - int startIllegalStateMsgPrefix = results.indexOf(IllegalStateMsgPrefix); - if (startIllegalStateMsgPrefix >= 0) { - int endIllegalStateMsgPrefix = startIllegalStateMsgPrefix + IllegalStateMsgPrefix.length(); - int startIllegalStateMsgPostfix = results.indexOf(']', endIllegalStateMsgPrefix); - if (startIllegalStateMsgPostfix < 0) { + String bundleNotFoundMsgPrefix = "BundleNotFoundException ["; + int startBundleNotFoundMsgPrefix = results.indexOf(bundleNotFoundMsgPrefix); + if (startBundleNotFoundMsgPrefix >= 0) { + int endBundleNotFoundMsgPrefix = startBundleNotFoundMsgPrefix + bundleNotFoundMsgPrefix.length(); + int startBundleNotFoundMsgPostfix = results.indexOf(']', endBundleNotFoundMsgPrefix); + if (startBundleNotFoundMsgPostfix < 0) { return 0; // this should never happen, we should always have the ending "]" bracket } - this.createInitialBundleVersionToken = results.substring(endIllegalStateMsgPrefix, - startIllegalStateMsgPostfix); + this.createInitialBundleVersionToken = results.substring(endBundleNotFoundMsgPrefix, + startBundleNotFoundMsgPostfix); return 0; }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java index 91043c6..b4bd2e9 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.bundle.BundleNotFoundException; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.enterprise.server.bundle.BundleManagerLocal; import org.rhq.enterprise.server.util.LookupUtil; @@ -54,8 +55,8 @@ public class BundleDistributionFileUploadServlet extends FileUploadServlet { BundleVersion bundleVersion = bundleManager.createOrStoreBundleVersionViaFile(subject, file); successMsg = "success [" + bundleVersion.getId() + "]";
- } catch (IllegalStateException e) { - writeExceptionResponse(response, "IllegalStateException [" + e.getMessage() + "]", e); // clients will look for this string! + } catch (BundleNotFoundException e) { + writeExceptionResponse(response, "BundleNotFoundException " + e.getMessage(), e); // clients will look for this string! return; } catch (Exception e) { writeExceptionResponse(response, "Failed to upload bundle distribution file", e); // clients will look for this string! diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java index eb96add..886e118 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java @@ -73,6 +73,7 @@ import org.rhq.core.domain.bundle.BundleDeploymentStatus; import org.rhq.core.domain.bundle.BundleDestination; import org.rhq.core.domain.bundle.BundleFile; import org.rhq.core.domain.bundle.BundleGroup; +import org.rhq.core.domain.bundle.BundleNotFoundException; import org.rhq.core.domain.bundle.BundleResourceDeployment; import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory; import org.rhq.core.domain.bundle.BundleType; @@ -617,7 +618,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
} catch (PermissionException e) { if (null != e.getCause() && e.getCause() instanceof BundleNotFoundException) { - throw new IllegalStateException("[" + distributionFile.getName() + "]"); + // This application exception indicates the special token handling workflow + throw new BundleNotFoundException("[" + distributionFile.getName() + "]"); } else { throw e; } @@ -740,7 +742,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot } catch (PermissionException e) { if (null != e.getCause() && e.getCause() instanceof BundleNotFoundException) { deleteFile = false; - throw new IllegalStateException("[" + file.getName() + "]"); + // This application exception indicates the special token handling workflow + throw new BundleNotFoundException("[" + file.getName() + "]"); } else { throw e; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleNotFoundException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleNotFoundException.java deleted file mode 100644 index 0563832..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleNotFoundException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2013 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.enterprise.server.bundle; - -import javax.ejb.ApplicationException; - -/** - * Indicates a required RHQ bundle did not exist. Note, we intentionally do not provide - * constructors that take a cause, since the three screen long Hibernate stack trace doesn't add any value here.<br/> - * Declare this an {@link ApplicationException} because we don't want these to be wrapped or to rollback an ongoing - * transaction. - */ -@ApplicationException(rollback = false, inherited = true) -public class BundleNotFoundException extends RuntimeException { - private static final long serialVersionUID = 1L; - - // Default no-arg constructor required by JAXB - public BundleNotFoundException() { - } - - /** - * Create an exception indicating the resource with the specified id was not found. - * - * @param bundleId a bundle id - */ - public BundleNotFoundException(int bundleId) { - super("A Bundle with id " + bundleId + " does not exist."); - } - - public BundleNotFoundException(String message) { - super(message); - } -} \ No newline at end of file
commit c8f2ed74a43d874b969aa45c8b00cd7fd1ca24c0 Author: Jay Shaughnessy jshaughn@redhat.com Date: Mon Aug 19 11:02:49 2013 -0400
fix test code to use updated api
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java index 033c7c7..bde66f2 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java @@ -793,7 +793,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { public void testAddBundleFilesToDifferentBundles() throws Exception { // create a bundle type to use for both bundles. BundleType bt = createBundleType("one"); - Bundle b1 = createBundle(overlord, "one", bt, 0); + Bundle b1 = createBundle(overlord, "one", bt, null); assertNotNull(b1); BundleVersion bv1 = createBundleVersion(b1.getName(), "1.0", b1); assertNotNull(bv1); @@ -801,7 +801,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { null, "Bundle #1 File # 1".getBytes());
// create a second bundle but create file of the same name as above - Bundle b2 = createBundle(overlord, "two", bt, 0); + Bundle b2 = createBundle(overlord, "two", bt, null); assertNotNull(b2); BundleVersion bv2 = createBundleVersion(b2.getName(), "1.0", b2); assertNotNull(bv2); @@ -2095,18 +2095,21 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { }
private Bundle createBundle(Subject subject, String name) throws Exception { - return createBundle(subject, name, 0); + return createBundle(subject, name, null); }
private Bundle createBundle(Subject subject, String name, int bundleGroupId) throws Exception { + return createBundle(subject, name, new int[] { bundleGroupId }); + } + + private Bundle createBundle(Subject subject, String name, int[] bundleGroupIds) throws Exception { BundleType bt = createBundleType(name); - return createBundle(subject, name, bt, bundleGroupId); + return createBundle(subject, name, bt, bundleGroupIds); }
- private Bundle createBundle(Subject subject, String name, BundleType bt, int bundleGroupId) throws Exception { + private Bundle createBundle(Subject subject, String name, BundleType bt, int[] bundleGroupIds) throws Exception { final String fullName = TEST_PREFIX + "-bundle-" + name; - Bundle b = bundleManager.createBundle(subject, fullName, fullName + "-desc", bt.getId(), - new int[] { bundleGroupId }); + Bundle b = bundleManager.createBundle(subject, fullName, fullName + "-desc", bt.getId(), bundleGroupIds);
assert b.getId() > 0; assert b.getName().endsWith(fullName);
commit 3b6937932d7b9eadcad387a44bad1adeacea1a7a Author: Jay Shaughnessy jshaughn@redhat.com Date: Mon Aug 19 10:34:48 2013 -0400
reverse the inverse relationship setting because as is Role.setBundleGroups would fail when trying to deserialize a bundle group update. (when calling updateRole)
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/authz/Role.java b/modules/core/domain/src/main/java/org/rhq/core/domain/authz/Role.java index 3f4c136..ed72d5f 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/authz/Role.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/authz/Role.java @@ -190,7 +190,6 @@ public class Role implements Serializable { }
public void addPermission(Permission permission) { - // permission.setRole(this); this.permissions.add(permission); }
@@ -229,7 +228,6 @@ public class Role implements Serializable { this.subjects = subjects; for (Subject subject : subjects) { subject.addRole(this); - this.subjects.add(subject); } } } @@ -286,37 +284,25 @@ public class Role implements Serializable { }
/** - * This also updates the inverse relations (add this role to bundle groups) - * @param bundleGroups + * This *does not* update the inverse relation. You may want {@link BundleGroup#addRole(Role)} */ public void setBundleGroups(Set<BundleGroup> bundleGroups) { - if (bundleGroups == null) { - this.bundleGroups = new HashSet<BundleGroup>(); - } else { - this.bundleGroups = bundleGroups; - for (BundleGroup bundleGroup : this.bundleGroups) { - bundleGroup.addRole(this); - this.bundleGroups.add(bundleGroup); - } - } + this.bundleGroups = bundleGroups; }
/** - * This also updates the inverse relation (add this role to bundle group) - * @param bundleGroup + * This *does not* update the inverse relation. You may want {@link BundleGroup#addRole(Role)} */ + public void addBundleGroup(BundleGroup bundleGroup) { getBundleGroups().add(bundleGroup); - bundleGroup.addRole(this); }
/** - * This also updates the inverse relation (remove this role from bundle group) - * @param bundleGroup + * This *does not* update the inverse relation. You may want {@link BundleGroup#removeRole(Role)} */ public void removeBundleGroup(BundleGroup bundleGroup) { getBundleGroups().remove(bundleGroup); - bundleGroup.removeRole(this); }
public Set<ResourceGroup> getResourceGroups() { @@ -330,7 +316,6 @@ public class Role implements Serializable { this.resourceGroups = resourceGroups; for (ResourceGroup resourceGroup : this.resourceGroups) { resourceGroup.addRole(this); - this.resourceGroups.add(resourceGroup); } } } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleGroup.java b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleGroup.java index dd6a824..e290f46 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleGroup.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/BundleGroup.java @@ -165,18 +165,20 @@ public class BundleGroup implements Serializable { }
/** - * This *does not* update the inverse relation. You may want {@link Role#addBundleGroup(BundleGroup)} + * This also updates the inverse relation (add this bundle group to role) * @param role */ public void addRole(Role role) { getRoles().add(role); + role.addBundleGroup(this); }
/** - * This *does not* update the inverse relation. You may want {@link Role#removeBundleGroup(BundleGroup)} + * This also updates the inverse relation (remove this bundle group from role) * @param role */ public boolean removeRole(Role role) { + role.removeBundleGroup(this); return getRoles().remove(role); }
commit ef1a138b14ce0742576c9ff886f62b3feae82f8d Author: Jay Shaughnessy jshaughn@redhat.com Date: Mon Aug 19 10:33:19 2013 -0400
Make sure to fetch the bundle groups so the selector is correctly seeded.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesDataSource.java index 047dacc..3e1fed4 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RolesDataSource.java @@ -320,6 +320,7 @@ public class RolesDataSource extends RPCDataSource<Role, RoleCriteria> { criteria.fetchSubjects(true); criteria.fetchResourceGroups(true); criteria.fetchLdapGroups(true); + criteria.fetchBundleGroups(true); }
// TODO: instead of fetching subjects and resource groups, use a composite object that will pull the subject
commit c166c9007d40283d9acf9da84918f700c2e92bac Author: John Mazzitelli mazz@redhat.com Date: Fri Aug 16 17:02:11 2013 -0400
sort the tree node better
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java index b46ce74..1be273d 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java @@ -28,6 +28,7 @@ import java.util.HashMap; import java.util.List; import java.util.Set;
+import com.google.gwt.i18n.client.NumberFormat; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; @@ -60,6 +61,9 @@ import org.rhq.enterprise.gui.coregui.client.util.StringUtility; */ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> {
+ // this is the field that will contain data which can be used to sort the tree nodes + public static final String FIELD_SORT_VALUE = "sortValue"; + private final BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
public BundleTreeDataSource() { @@ -80,6 +84,10 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { nameDataField.setCanEdit(false); fields.add(nameDataField);
+ DataSourceTextField sortValueDataField = new DataSourceTextField(FIELD_SORT_VALUE); + sortValueDataField.setCanView(false); + fields.add(sortValueDataField); + DataSourceTextField parentIdField = new DataSourceTextField("parentId", MSG.common_title_id_parent()); parentIdField.setForeignKey("id"); fields.add(parentIdField); @@ -314,6 +322,8 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { private ListGridRecord copyValuesForKnownBundle(Object from, Integer bundleGroupId, Integer bundleId) { String parentID; TreeNode node = new TreeNode(); + String sortValue = ""; + if (from instanceof BundleGroup) { BundleGroup bundleGroup = (BundleGroup) from; node.setIsFolder(true); @@ -323,6 +333,9 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> {
if (bundleGroup.getId() == 0) { node.setEnabled(false); + sortValue = "\uFFFDZZZZ"; // always show this as the last folder node in the tree + } else{ + sortValue = bundleGroup.getName(); } } else if (from instanceof Bundle) { Bundle bundle = (Bundle) from; @@ -331,7 +344,7 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { node.setID(String.valueOf(bundleGroupId) + "_" + bundle.getId()); node.setParentID(String.valueOf(bundleGroupId)); node.setName(StringUtility.escapeHtml(bundle.getName())); - + sortValue = bundle.getName(); } else if (from instanceof BundleVersion) { BundleVersion version = (BundleVersion) from; node.setIsFolder(false); @@ -340,6 +353,7 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { node.setParentID(parentID); node.setID(parentID + '_' + version.getId()); node.setName(version.getVersion()); + sortValue = NumberFormat.getFormat("000000").format(version.getVersionOrder());
} else if (from instanceof BundleDeployment) { BundleDeployment deployment = (BundleDeployment) from; @@ -354,6 +368,7 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { } else { node.setName(name); } + sortValue = deployment.getName();
} else if (from instanceof BundleDestination) { BundleDestination destination = (BundleDestination) from; @@ -363,8 +378,11 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { node.setParentID(parentID); node.setID(parentID + '_' + destination.getId()); node.setName(StringUtility.escapeHtml(destination.getName())); + sortValue = destination.getName(); }
+ node.setAttribute(FIELD_SORT_VALUE, sortValue.toLowerCase()); + return node; } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java index 7534ed0..1cdaf93 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java @@ -25,6 +25,7 @@ package org.rhq.enterprise.gui.coregui.client.bundle.tree; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; import com.smartgwt.client.types.SelectionStyle; +import com.smartgwt.client.types.SortDirection; import com.smartgwt.client.widgets.grid.events.DataArrivedEvent; import com.smartgwt.client.widgets.grid.events.DataArrivedHandler; import com.smartgwt.client.widgets.tree.Tree; @@ -59,7 +60,8 @@ public class BundleTreeView extends TreeGrid { setAnimateFolders(false); setSelectionType(SelectionStyle.SINGLE); setShowRollOver(false); - setSortField("name"); + setSortField(BundleTreeDataSource.FIELD_SORT_VALUE); + setSortDirection(SortDirection.ASCENDING); setShowHeader(false);
setDataSource(new BundleTreeDataSource());
commit 9a6f9afa3fd6d8adf3df5f3a59b86590043df8fb Author: Jay Shaughnessy jshaughn@redhat.com Date: Fri Aug 16 16:41:34 2013 -0400
Finish rough coding of integrating bundle group assignment into the bundle create wizard.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/composite/BundleGroupAssignmentComposite.java b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/composite/BundleGroupAssignmentComposite.java new file mode 100644 index 0000000..7c0cf97 --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/composite/BundleGroupAssignmentComposite.java @@ -0,0 +1,95 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, 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.core.domain.bundle.composite; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.bundle.Bundle; +import org.rhq.core.domain.bundle.BundleGroup; + +/** + * This composite is used to specify which bundle groups a bundle can be assigned to, for a particular user. + * + * @author Jay Shaughnessy + */ +public class BundleGroupAssignmentComposite implements Serializable { + private static final long serialVersionUID = 1L; + + private Subject subject; + private Bundle bundle; + private Map<BundleGroup, Boolean> bundleGroupMap; + private boolean canBeUnassigned = false; + + public BundleGroupAssignmentComposite() { + // GWT needs this + } + + public BundleGroupAssignmentComposite(Subject subject, Bundle bundle) { + // GWT needs this + } + + public Subject getSubject() { + return subject; + } + + public void setSubject(Subject subject) { + this.subject = subject; + } + + public Bundle getBundle() { + return bundle; + } + + public void setBundle(Bundle bundle) { + this.bundle = bundle; + } + + public Map<BundleGroup, Boolean> getBundleGroupMap() { + if (null == bundleGroupMap) { + bundleGroupMap = new HashMap<BundleGroup, Boolean>(); + } + return bundleGroupMap; + } + + public void setBundleGroupMap(Map<BundleGroup, Boolean> bundleGroupMap) { + this.bundleGroupMap = bundleGroupMap; + } + + public boolean isCanBeUnassigned() { + return canBeUnassigned; + } + + public void setCanBeUnassigned(boolean canBeUnassigned) { + this.canBeUnassigned = canBeUnassigned; + } + + @Override + public String toString() { + return "BundleGroupAssignmentComposite [subject=" + subject + ", bundle=" + bundle + ", bundleGroups=" + + bundleGroupMap.keySet() + ", canBeUnassigned=" + canBeUnassigned + "]"; + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java index 0729815..4613477 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java @@ -18,14 +18,14 @@ */ package org.rhq.enterprise.gui.coregui.client.bundle.create;
-import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.core.domain.bundle.BundleVersion; +import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizard; import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; @@ -41,7 +41,8 @@ public abstract class AbstractBundleCreateWizard extends AbstractWizard { private String createInitialBundleVersionToken; private String createInitialBundleVersionRecipe; private HashMap<String, Boolean> allBundleFilesStatus; // bundle file names with their upload status (true=they were uploaded) - private List<BundleGroup> initialBundleGroups = new ArrayList<BundleGroup>(); + private BundleGroupAssignmentComposite bundleGroupAssignmentComposite; + private Set<BundleGroup> initialBundleGroups;
public String getRecipe() { return recipe; @@ -90,12 +91,19 @@ public abstract class AbstractBundleCreateWizard extends AbstractWizard { return ((null != createInitialBundleVersionToken) || (null != createInitialBundleVersionRecipe)); }
- - public List<BundleGroup> getInitialBundleGroups() { + public BundleGroupAssignmentComposite getBundleGroupAssignmentComposite() { + return bundleGroupAssignmentComposite; + } + + public void setBundleGroupAssignmentComposite(BundleGroupAssignmentComposite bundleGroupAssignmentComposite) { + this.bundleGroupAssignmentComposite = bundleGroupAssignmentComposite; + } + + public Set<BundleGroup> getInitialBundleGroups() { return initialBundleGroups; }
- public void setInitialBundleGroups(List<BundleGroup> initialBundleGroups) { + public void setInitialBundleGroups(Set<BundleGroup> initialBundleGroups) { this.initialBundleGroups = initialBundleGroups; }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java index 335f2d6..2d6ebbc 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java @@ -22,31 +22,143 @@ */ package org.rhq.enterprise.gui.coregui.client.bundle.create;
+import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.Set;
+import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.Overflow; +import com.smartgwt.client.types.TitleOrientation; import com.smartgwt.client.widgets.Canvas; +import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.FormItem; +import com.smartgwt.client.widgets.form.fields.RadioGroupItem; +import com.smartgwt.client.widgets.form.fields.SpacerItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; +import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; +import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; +import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.bundle.BundleGroup; +import org.rhq.core.domain.bundle.BundleVersion; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.bundle.group.BundleGroupSelector; +import org.rhq.enterprise.gui.coregui.client.bundle.group.BundleGroupsDataSource; import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep; +import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.util.FormUtility; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; +import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/** * @author Jay Shaughnessy */ public class BundleGroupsStep extends AbstractWizardStep {
+ private EnhancedVLayout canvas; + private DynamicForm radioForm; + private final BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(); private AbstractBundleCreateWizard wizard = null; - private BundleGroupSelector selector = null; + private boolean isInitialVersion; + private BundleGroupSelector selector;
public BundleGroupsStep(AbstractBundleCreateWizard wizard) { this.wizard = wizard; }
public Canvas getCanvas() { - if (selector == null) { - selector = new BundleGroupSelector(); + canvas = new EnhancedVLayout(); + canvas.setWidth100(); + + radioForm = new DynamicForm(); + radioForm.setNumCols(1); + // These settings (as opposed to setWidth100()) allow for contextual help to be better placed + radioForm.setAutoWidth(); + radioForm.setOverflow(Overflow.VISIBLE); + + List<FormItem> formItems = new ArrayList<FormItem>(); + + // Make the radio item title a separate item in the form in order to add contextual help + // to the right of the title text. We could also add it to the radio item but then it floats to + // the right of the last radio button option (I'll leave that commented below if for some reason + // we want to switch to that approach. + StaticTextItem radioTitleItem = new StaticTextItem("RadioTitle"); + radioTitleItem.setShowTitle(false); + radioTitleItem.setTitleOrientation(TitleOrientation.TOP); + radioTitleItem.setAlign(Alignment.LEFT); + // The css style "formTitle" is what should work here, but for some reason I wasn't getting the + // proper color. So instead I grabbed the color from the smartgwt css and declared it explicitly. + //radioTitleItem.setCellStyle("formTitle"); + radioTitleItem.setValue("<span style="font-weight: bold; color: #003168">" + + "The assigned bundle groups (I18N)" + " :</span>"); + FormUtility.addContextualHelp(radioTitleItem, "Add actual help (I18N)"); + formItems.add(radioTitleItem); + + RadioGroupItem radioGroupItem = new RadioGroupItem("RadioOptions"); + radioGroupItem.setShowTitle(false); + radioGroupItem.setRequired(true); + radioGroupItem.setAlign(Alignment.LEFT); + // TODO: I18N + LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); + if (wizard.getBundleGroupAssignmentComposite().isCanBeUnassigned()) { + valueMap.put("unassigned", "Leave Unassigned"); } - return selector; + valueMap.put("assigned", "Assign to at least one Bundle Group"); + radioGroupItem.setValueMap(valueMap); + + radioGroupItem.addChangedHandler(new ChangedHandler() { + public void onChanged(ChangedEvent event) { + if ("unassigned".equals(event.getValue())) { + //SC.say(MSG.view_drift_wizard_pinTemplate_infoStepSelectBlocked()); + // event.getItem().setValue(CREATE_TEMPLATE); + selector.disable(); + return; + + } else { + selector.enable(); + } + + canvas.markForRedraw(); + } + }); + + formItems.add(radioGroupItem); + formItems.add(new SpacerItem()); + canvas.addMember(radioForm); + + // go get the assignable/assigned bundle groups for this new bundle version, initial or not + this.isInitialVersion = this.wizard.getBundleVersion() == null + || this.wizard.getBundleVersion().getVersionOrder() == 0; + + Map<BundleGroup, Boolean> map = wizard.getBundleGroupAssignmentComposite().getBundleGroupMap(); + if (map.isEmpty()) { + selector = new BundleGroupSelector(!isInitialVersion); + + } else { + Set<BundleGroup> bundleGroups = map.keySet(); + Integer[] idsFilter = new Integer[bundleGroups.size()]; + int i = 0; + for (BundleGroup bundleGroup : bundleGroups) { + idsFilter[i++] = bundleGroup.getId(); + } + + List<ListGridRecord> initiallyAssigned = new ArrayList<ListGridRecord>(bundleGroups.size()); + BundleGroupsDataSource ds = new BundleGroupsDataSource(); + for (BundleGroup bundleGroup : bundleGroups) { + if (map.get(bundleGroup) == Boolean.TRUE) { + initiallyAssigned.add(ds.copyValues(bundleGroup)); + } + } + selector = new BundleGroupSelector(idsFilter, + initiallyAssigned.toArray(new ListGridRecord[initiallyAssigned.size()]), !isInitialVersion); + } + canvas.addMember(selector); + + return canvas; }
public Set<BundleGroup> getSelectedBundleGroups() { @@ -54,11 +166,119 @@ public class BundleGroupsStep extends AbstractWizardStep { }
public boolean nextPage() { - return true; + if (null == wizard.getBundleVersion()) { + if (null != wizard.getCreateInitialBundleVersionRecipe()) { + processRecipe(); + } else if (null != wizard.getCreateInitialBundleVersionToken()) { + processToken(); + } else { + Exception e = new IllegalStateException( + "Unexpected error: can't create initial version, no recipe or token"); + wizard.getView().showMessage(e.getMessage()); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), e); + wizard.setBundleVersion(null); + wizard.setCreateInitialBundleVersionRecipe(""); + } + } else { + processAssignment(); + } + + return false; + } + + private int[] getInitialBundleIds() { + if (selector.isDisabled()) { + return null; + } + + Set<BundleGroup> bundleGroups = selector.getSelectedItems(); + + wizard.setInitialBundleGroups(bundleGroups); + + int[] result = new int[bundleGroups.size()]; + int i = 0; + for (BundleGroup bundleGroup : bundleGroups) { + result[i++] = bundleGroup.getId(); + } + + return result; + } + + private void processRecipe() { + + BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(); + bundleServer.createInitialBundleVersionViaRecipe(getInitialBundleIds(), + this.wizard.getCreateInitialBundleVersionRecipe(), new AsyncCallback<BundleVersion>() { + @Override + public void onSuccess(BundleVersion result) { + CoreGUI.getMessageCenter().notify( + new Message( + MSG.view_bundle_createWizard_createSuccessful(result.getName(), result.getVersion()), + Message.Severity.Info)); + wizard.setBundleVersion(result); + wizard.getView().incrementStep(); // go to the next step + } + + @Override + public void onFailure(Throwable caught) { + wizard.getView().showMessage(caught.getMessage()); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); + wizard.setBundleVersion(null); + wizard.setCreateInitialBundleVersionRecipe(""); + } + }); + } + + private void processToken() { + + BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(); + bundleServer.createInitialBundleVersionViaToken(getInitialBundleIds(), + this.wizard.getCreateInitialBundleVersionToken(), new AsyncCallback<BundleVersion>() { + @Override + public void onSuccess(BundleVersion result) { + CoreGUI.getMessageCenter().notify( + new Message( + MSG.view_bundle_createWizard_createSuccessful(result.getName(), result.getVersion()), + Message.Severity.Info)); + wizard.setBundleVersion(result); + wizard.getView().incrementStep(); // go to the next step + } + + @Override + public void onFailure(Throwable caught) { + wizard.getView().showMessage(caught.getMessage()); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); + wizard.setBundleVersion(null); + wizard.setCreateInitialBundleVersionToken(""); + } + }); + } + + private void processAssignment() { + + BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(); + bundleServer.assignBundlesToBundleGroups(getInitialBundleIds(), new int[] { wizard.getBundleVersion() + .getBundle().getId() }, new AsyncCallback<Void>() { + @Override + public void onSuccess(Void result) { + // I18N + CoreGUI.getMessageCenter().notify( + new Message("MSG.view_bundle_createWizard_assignSuccessful(result.getName(), result.getVersion())", + Message.Severity.Info)); + wizard.getView().incrementStep(); // go to the next step + } + + @Override + public void onFailure(Throwable caught) { + wizard.getView().showMessage(caught.getMessage()); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); + wizard.setBundleVersion(null); + wizard.setCreateInitialBundleVersionRecipe(""); + } + }); }
public String getName() { return MSG.common_title_bundleGroups(); } - } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java index a248efc..9344fb6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java @@ -38,6 +38,7 @@ import com.smartgwt.client.widgets.form.fields.events.ClickEvent; import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import org.rhq.core.domain.bundle.BundleVersion; +import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.core.domain.criteria.BundleVersionCriteria; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.gui.coregui.client.CoreGUI; @@ -274,7 +275,7 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { Message.Severity.Info)); wizard.setBundleVersion(result); setButtonsDisableMode(false); - wizard.getView().incrementStep(); // go to the next step + incrementStep(); // go to the next step }
@Override @@ -306,7 +307,30 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep {
wizard.setCreateInitialBundleVersionToken(token); setButtonsDisableMode(false); - wizard.getView().incrementStep(); // go to the next step + incrementStep(); // go to the next step + } + + private void incrementStep() { + // before moving to the next step, get the assignable/assigned bundle groups for this new bundle version + boolean isInitialVersion = this.wizard.getBundleVersion() == null + || this.wizard.getBundleVersion().getVersionOrder() == 0; + int bundleId = isInitialVersion ? 0 : this.wizard.getBundleVersion().getBundle().getId(); + + BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(); + bundleServer.getAssignableBundleGroups(bundleId, new AsyncCallback<BundleGroupAssignmentComposite>() { + + public void onSuccess(BundleGroupAssignmentComposite result) { + wizard.setBundleGroupAssignmentComposite(result); + wizard.getView().incrementStep(); // go to the next step + } + + public void onFailure(Throwable caught) { + setButtonsDisableMode(false); + // TODO NEW MESSAGE + CoreGUI.getErrorHandler().handleError("Failed to determine assignable bundle groups.", caught); + } + }); + }
private void processUpload() { @@ -325,7 +349,7 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { Message.Severity.Info)); wizard.setBundleVersion(bv); setButtonsDisableMode(false); - wizard.getView().incrementStep(); // go to the next step + incrementStep(); // go to the next step }
@Override @@ -337,8 +361,7 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { } }); } else if (null != uploadDistroForm.getCreateInitialBundleVersionToken()) { - handleIllegalStateException(new IllegalStateException( - uploadDistroForm.getCreateInitialBundleVersionToken())); + handleIllegalStateException(new IllegalStateException(uploadDistroForm.getCreateInitialBundleVersionToken()));
} else { String errorMessage = uploadDistroForm.getUploadError(); @@ -368,7 +391,7 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { Message.Severity.Info)); wizard.setBundleVersion(result); setButtonsDisableMode(false); - wizard.getView().incrementStep(); // go to the next step + incrementStep(); // go to the next step }
@Override @@ -380,7 +403,7 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { handled = true; wizard.setCreateInitialBundleVersionRecipe(wizard.getRecipe()); setButtonsDisableMode(false); - wizard.getView().incrementStep(); // go to the next step + incrementStep(); // go to the next step }
if (!handled) { @@ -423,6 +446,5 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { radioGroup.destroyComponents(); super.destroy(); } - } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupSelector.java index 3a5c047..4c5e219 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupSelector.java @@ -22,6 +22,7 @@ import com.smartgwt.client.data.Criteria; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.core.domain.criteria.BundleGroupCriteria; @@ -33,13 +34,27 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; */ public class BundleGroupSelector extends AbstractSelector<BundleGroup, BundleGroupCriteria> {
+ private Integer[] idsFilter;
public BundleGroupSelector() { - this(false); + this(null, null, false); }
- public BundleGroupSelector(boolean isReadOnly) { + public BundleGroupSelector(boolean isReadonly) { + this(null, null, isReadonly); + } + + /** + * @param idsFilter optionally narrow the results to some predefined set, typically when narrowing to + * bundle groups associated with roles having specific permissions. ignored if null. + * @param initiallyAssigned + * @param isReadOnly + */ + public BundleGroupSelector(Integer[] idsFilter, ListGridRecord[] initiallyAssigned, boolean isReadOnly) { super(isReadOnly); + setAssigned(initiallyAssigned); + + this.idsFilter = idsFilter; }
protected DynamicForm getAvailableFilterForm() { @@ -77,6 +92,9 @@ public class BundleGroupSelector extends AbstractSelector<BundleGroup, BundleGro if (null != result) { result.setStrict(false); } + if (null != idsFilter) { + result.addFilterIds(idsFilter); + } return result; } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java index 4e80e6c..ddfb9b6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java @@ -20,7 +20,6 @@ package org.rhq.enterprise.gui.coregui.client.gwt;
import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet;
import com.google.gwt.user.client.rpc.RemoteService;
@@ -33,6 +32,7 @@ import org.rhq.core.domain.bundle.BundleResourceDeployment; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration; +import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.core.domain.bundle.composite.BundleWithLatestVersionComposite; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.criteria.BundleCriteria; @@ -53,6 +53,8 @@ public interface BundleGWTService extends RemoteService {
BundleVersion createInitialBundleVersionViaRecipe(int[] bundleGroupIds, String recipe) throws RuntimeException;
+ BundleVersion createInitialBundleVersionViaToken(int[] bundleGroupIds, String token) throws RuntimeException; + BundleVersion createBundleVersionViaRecipe(String recipe) throws RuntimeException;
BundleDeployment createBundleDeployment(int bundleVersionId, int bundleDestinationId, String description, @@ -113,6 +115,9 @@ public interface BundleGWTService extends RemoteService {
BundleGroup updateBundleGroup(BundleGroup bundleGroup) throws RuntimeException;
- HashSet<BundleGroup> getCreateBundleGroups() throws RuntimeException; + BundleGroupAssignmentComposite getAssignableBundleGroups(int bundleId) throws RuntimeException; + + void assignBundlesToBundleGroups(int[] bundleGroupIds, int[] bundleIds) throws RuntimeException;
+ void unassignBundlesFromBundleGroups(int[] bundleGroupIds, int[] bundleIds) throws RuntimeException; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java index ce229b9..eba043c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java @@ -20,10 +20,8 @@ package org.rhq.enterprise.gui.coregui.server.gwt;
import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet;
-import org.rhq.core.domain.authz.Permission; -import org.rhq.core.domain.authz.Role; +import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.bundle.Bundle; import org.rhq.core.domain.bundle.BundleDeployment; import org.rhq.core.domain.bundle.BundleDestination; @@ -33,6 +31,7 @@ import org.rhq.core.domain.bundle.BundleResourceDeployment; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration; +import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.core.domain.bundle.composite.BundleWithLatestVersionComposite; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.criteria.BundleCriteria; @@ -42,7 +41,6 @@ import org.rhq.core.domain.criteria.BundleFileCriteria; import org.rhq.core.domain.criteria.BundleGroupCriteria; import org.rhq.core.domain.criteria.BundleResourceDeploymentCriteria; import org.rhq.core.domain.criteria.BundleVersionCriteria; -import org.rhq.core.domain.criteria.RoleCriteria; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTService; import org.rhq.enterprise.gui.coregui.server.util.SerialUtility; @@ -111,6 +109,17 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override + public BundleVersion createInitialBundleVersionViaToken(int[] bundleGroupIds, String token) throws RuntimeException { + try { + BundleVersion results = bundleManager.createInitialBundleVersionViaToken(getSessionSubject(), + bundleGroupIds, token); + return SerialUtility.prepare(results, "createInitialBundleVersionViaToken"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override public BundleDeployment createBundleDeployment(int bundleVersionId, int bundleDestinationId, String description, Configuration configuration, boolean enforcePolicy, int enforcementInterval, boolean pinToBundle) throws RuntimeException { @@ -358,26 +367,32 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override - public HashSet<BundleGroup> getCreateBundleGroups() throws RuntimeException { + public BundleGroupAssignmentComposite getAssignableBundleGroups(int bundleId) throws RuntimeException { try { - RoleCriteria c = new RoleCriteria(); - c.addFilterSubjectId(getSessionSubject().getId()); - ArrayList<Permission> l = new ArrayList<Permission>(1); - l.add(Permission.CREATE_BUNDLES_IN_GROUP); - c.addFilterPermissions(l); - c.fetchBundleGroups(true); - - PageList<Role> roles = LookupUtil.getRoleManager().findRolesByCriteria( - LookupUtil.getSubjectManager().getOverlord(), c); + Subject subject = getSessionSubject(); + BundleGroupAssignmentComposite results = bundleManager + .getAssignableBundleGroups(subject, subject, bundleId); + return SerialUtility.prepare(results, "getAssignableBundleGroups"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + }
- HashSet<BundleGroup> result = new HashSet<BundleGroup>(); - for (Role role : roles) { - for (BundleGroup bundleGroup : role.getBundleGroups()) { - result.add(bundleGroup); - } - } + @Override + public void assignBundlesToBundleGroups(int[] bundleGroupIds, int[] bundleIds) throws RuntimeException { + try { + Subject subject = getSessionSubject(); + bundleManager.assignBundlesToBundleGroups(subject, bundleGroupIds, bundleIds); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + }
- return SerialUtility.prepare(result, "getCreateBundleGroups"); + @Override + public void unassignBundlesFromBundleGroups(int[] bundleGroupIds, int[] bundleIds) throws RuntimeException { + try { + Subject subject = getSessionSubject(); + bundleManager.unassignBundlesFromBundleGroups(subject, bundleGroupIds, bundleIds); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java index b85e650..033c7c7 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java @@ -1424,7 +1424,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
try { - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() }); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1432,19 +1433,23 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// allow bundle assign via global manage_bundle_groups addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() });
// allow bundle unassign via global manage_bundle_groups - bundleManager.unassignBundlesFromBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.unassignBundlesFromBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() });
// allow bundle assign via global create removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); addRolePermissions(role, Permission.CREATE_BUNDLES); - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() });
// deny bundle unassign via global create try { - bundleManager.unassignBundlesFromBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.unassignBundlesFromBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() }); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1452,13 +1457,15 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// allow bundle unassign via global delete addRolePermissions(role, Permission.DELETE_BUNDLES); - bundleManager.unassignBundlesFromBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.unassignBundlesFromBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() }); removeRolePermissions(role, Permission.DELETE_BUNDLES);
// deny bundle assign with global create but no view removeRolePermissions(role, Permission.VIEW_BUNDLES); try { - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() }); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1466,7 +1473,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// go back and again assign via global create and view addRolePermissions(role, Permission.VIEW_BUNDLES); - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup.getId() }, + new int[] { bundle.getId() });
// deny assigned, unassociated-bundle-group bundle view removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); @@ -1602,7 +1610,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// deny bundle assign to bg2 (not associated with role) try { - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup2.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup2.getId() }, + new int[] { bundle.getId() }); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1614,7 +1623,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { // deny bundle assign to bg2 (no perm) removeRolePermissions(role2, Permission.CREATE_BUNDLES_IN_GROUP); try { - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup2.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup2.getId() }, + new int[] { bundle.getId() }); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1622,7 +1632,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// allow bundle assign to bg2 addRolePermissions(role2, Permission.ASSIGN_BUNDLES_TO_GROUP); - bundleManager.assignBundlesToBundleGroup(subject, bundleGroup2.getId(), new int[] { bundle.getId() }); + bundleManager.assignBundlesToBundleGroups(subject, new int[] { bundleGroup2.getId() }, + new int[] { bundle.getId() });
// should fetch the single bundle even though it is in two groups BundleCriteria bundleCriteria = new BundleCriteria(); @@ -1641,7 +1652,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// deny unassign try { - bundleManager.unassignBundlesFromBundleGroup(subject, bundleGroup2.getId(), new int[] { bundle.getId() }); + bundleManager.unassignBundlesFromBundleGroups(subject, new int[] { bundleGroup2.getId() }, + new int[] { bundle.getId() }); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1650,8 +1662,10 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { // allow unassigns addRolePermissions(role, Permission.UNASSIGN_BUNDLES_FROM_GROUP); addRolePermissions(role2, Permission.UNASSIGN_BUNDLES_FROM_GROUP); - bundleManager.unassignBundlesFromBundleGroup(subject, bundleGroup1.getId(), new int[] { bundle.getId() }); - bundleManager.unassignBundlesFromBundleGroup(subject, bundleGroup2.getId(), new int[] { bundle.getId() }); + bundleManager.unassignBundlesFromBundleGroups(subject, new int[] { bundleGroup1.getId() }, + new int[] { bundle.getId() }); + bundleManager.unassignBundlesFromBundleGroups(subject, new int[] { bundleGroup2.getId() }, + new int[] { bundle.getId() });
// should not find the now unassigned bundle bundles = bundleManager.findBundlesByCriteria(subject, bundleCriteria); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java index b8e16f0..eb96add 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java @@ -78,6 +78,7 @@ import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration; +import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.core.domain.bundle.composite.BundleWithLatestVersionComposite; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; @@ -97,6 +98,7 @@ import org.rhq.core.domain.criteria.BundleVersionCriteria; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.criteria.ResourceTypeCriteria; +import org.rhq.core.domain.criteria.RoleCriteria; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.group.ResourceGroup; @@ -124,6 +126,7 @@ import org.rhq.enterprise.server.util.CriteriaQuery; import org.rhq.enterprise.server.util.CriteriaQueryExecutor; import org.rhq.enterprise.server.util.CriteriaQueryGenerator; import org.rhq.enterprise.server.util.CriteriaQueryRunner; +import org.rhq.enterprise.server.util.LookupUtil;
/** * Manages the creation and usage of bundles. @@ -2004,21 +2007,24 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - public void assignBundlesToBundleGroup(Subject subject, int bundleGroupId, int[] bundleIds) { - BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); - if (null == bundleGroup) { - throw new IllegalArgumentException("BundleGroup does not exist for bundleGroupId [" + bundleGroupId + "]"); - } + public void assignBundlesToBundleGroups(Subject subject, int bundleGroupIds[], int[] bundleIds) { + for (int bundleGroupId : bundleGroupIds) { + BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); + if (null == bundleGroup) { + throw new IllegalArgumentException("BundleGroup does not exist for bundleGroupId [" + bundleGroupId + + "]"); + }
- checkAssignBundleGroupAuthz(subject, bundleGroupId, bundleIds); + checkAssignBundleGroupAuthz(subject, bundleGroupId, bundleIds);
- for (int bundleId : bundleIds) { - Bundle bundle = entityManager.find(Bundle.class, bundleId); - if (null == bundle) { - throw new IllegalArgumentException("Bundle does not exist for bundleId [" + bundleId + "]"); - } + for (int bundleId : bundleIds) { + Bundle bundle = entityManager.find(Bundle.class, bundleId); + if (null == bundle) { + throw new IllegalArgumentException("Bundle does not exist for bundleId [" + bundleId + "]"); + }
- bundleGroup.addBundle(bundle); + bundleGroup.addBundle(bundle); + } } }
@@ -2047,7 +2053,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot for (Bundle b : bundles) { bundleIds[i++] = b.getId(); } - assignBundlesToBundleGroup(subject, bundleGroup.getId(), bundleIds); + assignBundlesToBundleGroups(subject, new int[] { bundleGroup.getId() }, bundleIds); }
return bundleGroup; @@ -2096,21 +2102,24 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - public void unassignBundlesFromBundleGroup(Subject subject, int bundleGroupId, int[] bundleIds) { - BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); - if (null == bundleGroup) { - throw new IllegalArgumentException("BundleGroup does not exist for bundleGroupId [" + bundleGroupId + "]"); - } + public void unassignBundlesFromBundleGroups(Subject subject, int[] bundleGroupIds, int[] bundleIds) { + for (int bundleGroupId : bundleGroupIds) { + BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); + if (null == bundleGroup) { + throw new IllegalArgumentException("BundleGroup does not exist for bundleGroupId [" + bundleGroupId + + "]"); + }
- checkUnassignBundleGroupAuthz(subject, bundleGroupId, bundleIds); + checkUnassignBundleGroupAuthz(subject, bundleGroupId, bundleIds);
- for (int bundleId : bundleIds) { - Bundle bundle = entityManager.find(Bundle.class, bundleId); - if (null == bundle) { - throw new IllegalArgumentException("Bundle does not exist for bundleId [" + bundleId + "]"); - } + for (int bundleId : bundleIds) { + Bundle bundle = entityManager.find(Bundle.class, bundleId); + if (null == bundle) { + throw new IllegalArgumentException("Bundle does not exist for bundleId [" + bundleId + "]"); + }
- bundleGroup.removeBundle(bundle); + bundleGroup.removeBundle(bundle); + } } }
@@ -2447,4 +2456,93 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
}
+ @Override + public BundleGroupAssignmentComposite getAssignableBundleGroups(Subject subject, Subject assigningSubject, + int bundleId) throws Exception { + + Bundle bundle = null; + + if (0 != bundleId) { + bundle = entityManager.find(Bundle.class, bundleId); + if (null == bundle) { + throw new BundleNotFoundException("Bundle ID [" + bundleId + "]"); + } + } + + BundleGroupAssignmentComposite result = new BundleGroupAssignmentComposite(assigningSubject, bundle); + Set<Permission> globalPermissions = authorizationManager.getExplicitGlobalPermissions(assigningSubject); + boolean hasManageBundleGroups = globalPermissions.contains(Permission.MANAGE_BUNDLE_GROUPS); + + // can assign any bundle anywhere, or leave unassigned + if (hasManageBundleGroups) { + BundleGroupCriteria criteria = new BundleGroupCriteria(); + // just get all the bundle groups by using overlord and no filters + List<BundleGroup> bundleGroups = findBundleGroupsByCriteria(subjectManager.getOverlord(), criteria); + result.setCanBeUnassigned(true); + result.setBundleGroupMap(populateBundleGroupMap(bundleGroups, bundle)); + return result; + } + + boolean hasViewBundles = globalPermissions.contains(Permission.VIEW_BUNDLES); + boolean hasCreateBundles = globalPermissions.contains(Permission.CREATE_BUNDLES); + boolean isNewBundle = (null == bundle); + ArrayList<Permission> permFilter = new ArrayList<Permission>(1); + + if (isNewBundle) { + // set whether can leave unassigned + result.setCanBeUnassigned(hasCreateBundles && hasViewBundles); + // can assign to bundle groups for which he has create_bundles_in_group + permFilter.add(Permission.CREATE_BUNDLES_IN_GROUP); + + } else { + // if necessary, make sure the bundle is viewable + if (!hasViewBundles) { + if (authorizationManager.canViewBundle(assigningSubject, bundleId)) { + throw new PermissionException("Bundle ID [" + bundleId + "] is not viewable by subject [" + + assigningSubject.getName() + "]"); + } + } + + // can assign to bundle groups for which he has create_bundles_in_group or assign_bundles_to_group + permFilter.add(Permission.CREATE_BUNDLES_IN_GROUP); + permFilter.add(Permission.ASSIGN_BUNDLES_TO_GROUP); + } + + List<BundleGroup> bundleGroups; + if (hasCreateBundles) { + // can assign to any viewable bundle group + // get all the viewable bundle groups for the subject, no filters + BundleGroupCriteria criteria = new BundleGroupCriteria(); + bundleGroups = findBundleGroupsByCriteria(assigningSubject, criteria); + + } else { + // can only assign to bundle groups for which he has the necessary permissions + RoleCriteria criteria = new RoleCriteria(); + criteria.addFilterSubjectId(assigningSubject.getId()); + criteria.addFilterPermissions(permFilter); + criteria.fetchBundleGroups(true); + List<Role> roles = LookupUtil.getRoleManager().findRolesByCriteria(subjectManager.getOverlord(), criteria); + bundleGroups = new ArrayList<BundleGroup>(); + for (Role role : roles) { + for (BundleGroup bundleGroup : role.getBundleGroups()) { + if (!bundleGroups.contains(bundleGroup)) { + bundleGroups.add(bundleGroup); + } + } + } + } + + result.setBundleGroupMap(populateBundleGroupMap(bundleGroups, bundle)); + return result; + } + + private Map<BundleGroup, Boolean> populateBundleGroupMap(List<BundleGroup> bundleGroups, Bundle bundle) { + Map<BundleGroup, Boolean> result = new HashMap<BundleGroup, Boolean>(bundleGroups.size()); + for (BundleGroup bundleGroup : bundleGroups) { + Boolean assigned = ((null != bundle) && bundle.getBundleGroups().contains(bundleGroup)) ? Boolean.TRUE + : Boolean.FALSE; + result.put(bundleGroup, assigned); + } + return result; + } } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java index 64365c4..1aca6ac 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java @@ -33,6 +33,7 @@ import org.rhq.core.domain.bundle.BundleResourceDeployment; import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.BundleVersion; +import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.core.domain.configuration.Configuration;
/** @@ -323,4 +324,18 @@ public interface BundleManagerLocal extends BundleManagerRemote { BundleVersion createInitialBundleVersionViaToken(Subject subject, int[] bundleGroupIds, String token) throws Exception;
+ /** + * For the calling subject determines which bundle groups to which the user can assign the bundle. The composite + * includes a <code>Map<BundleGroup,Boolean></code> indicating the assignable BundleGroups and which are + * currently assigned. It also indicates whether the bundle can be left unassigned. When querying for + * new bundles the bundleId should be set to 0. + * + * @param subject, the calling subject + * @param assigningSubject, the subject relevant to the bundle group assignment + * @param bundleId, the bundle relevant to the bundle group assignment, or 0 for a new bundle + * @return + * @throws Exception + */ + BundleGroupAssignmentComposite getAssignableBundleGroups(Subject subject, Subject assigningSubject, int bundleId) + throws Exception; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java index b3d849a..0148aa2 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java @@ -146,7 +146,7 @@ public interface BundleManagerRemote { throws Exception;
/** - * Assign the specified bundles to the specified bundle group. This adds bundles that were not previously + * Assign the specified bundles to the specified bundle groups. This adds bundles that were not previously * assigned. Others are ignored. * <pre> * Requires VIEW permission for the relevant bundle and one of: @@ -156,10 +156,10 @@ public interface BundleManagerRemote { * - BundleGroup.CREATE_BUNDLES_IN_GROUP for the relevant bundle group * </pre> * @param subject - * @param bundleGroupId + * @param bundleGroupIds * @param bundleIds */ - void assignBundlesToBundleGroup(Subject subject, int bundleGroupId, int[] bundleIds); + void assignBundlesToBundleGroups(Subject subject, int[] bundleGroupIds, int[] bundleIds);
/** * Create a new bundle deployment. Note that bundle deployment names are generated by this @@ -628,7 +628,7 @@ public interface BundleManagerRemote { String deploymentDescription, boolean isCleanDeployment) throws Exception;
/** - * Unassign the specified bundles from the specified bundle group. This removes bundles that were previously + * Unassign the specified bundles from the specified bundle groups. This removes bundles that were previously * assigned. Others are ignored. * <pre> * Requires VIEW permission for the relevant bundles and one of: @@ -641,7 +641,7 @@ public interface BundleManagerRemote { * @param bundleGroupId * @param bundleIds */ - void unassignBundlesFromBundleGroup(Subject subject, int bundleGroupId, int[] bundleIds); + void unassignBundlesFromBundleGroups(Subject subject, int[] bundleGroupIds, int[] bundleIds);
/** * Updates an existing bundle group. The set of bundles will be updated if non-null.
commit 05bf9af581c6382c6df33b128eafae0232536729 Author: Jay Shaughnessy jshaughn@redhat.com Date: Fri Aug 16 16:38:43 2013 -0400
remove dead src branch
diff --git a/.classpath b/.classpath index a61ef29..335117b 100644 --- a/.classpath +++ b/.classpath @@ -209,7 +209,6 @@ <classpathentry kind="src" path="modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java"/> <classpathentry kind="src" path="modules/common/cassandra-ccm/cassandra-ccm-testng/src/main/java"/> <classpathentry kind="src" path="modules/common/cassandra-ccm/cassandra-ccm-testng/src/test/java"/> - <classpathentry kind="src" path="modules/common/cassandra-jmx/src/main/java"/> <classpathentry kind="src" path="modules/plugins/rhq-storage/src/main/java"/> <classpathentry kind="src" path="modules/enterprise/server/data-migration/src/main/java"/> <classpathentry kind="src" path="modules/enterprise/server/data-migration/src/test/java"/>
commit a08919223a16eef5f23869f03341c448a347cfbf Author: Jay Shaughnessy jshaughn@redhat.com Date: Fri Aug 16 08:16:43 2013 -0400
Interim check-in of work supporting bundle group selection in the bundle create wizard - not working
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java index a07f012..b44f62d 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RoleCriteria.java @@ -22,9 +22,12 @@ */ package org.rhq.core.domain.criteria;
+import java.util.List; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType;
+import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.util.PageOrdering;
@@ -41,6 +44,7 @@ public class RoleCriteria extends Criteria { private String filterName; private Integer filterSubjectId; // needs overrides private Integer filterLdapSubjectId; // needs overrides + private List<Permission> filterPermissions; // needs override
private boolean fetchPermissions; private boolean fetchResourceGroups; @@ -63,6 +67,12 @@ public class RoleCriteria extends Criteria { + " FROM Role innerRole " // + " JOIN innerRole.ldapSubjects innerSubject " // + " WHERE innerSubject.id = ? )"); + + filterOverrides.put("permissions", "" // + + "id IN ( SELECT innerRole.id " // + + " FROM Role innerRole " // + + " JOIN irole.permissions perm " // + + " WHERE perm IN ( ? ) )"); }
@Override @@ -86,6 +96,10 @@ public class RoleCriteria extends Criteria { this.filterLdapSubjectId = filterLdapSubjectId; }
+ public void addFilterPermissions(List<Permission> filterPermissions) { + this.filterPermissions = filterPermissions; + } + /** * Requires MANAGE_SECURITY * diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java index d232576..7d5e6c4 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java @@ -119,7 +119,7 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView { ViewPath nextViewPath = viewPath.next(); // the ID segment
if ("Bundle".equals(currentPath)) { - if (!nextViewPath.equals(currentBundleViewId)) { + if (!nextViewPath.getCurrent().equals(currentBundleViewId)) { // set new bundle detail currentBundleViewId = nextViewPath.getCurrent(); bundleView = new BundleView(globalPermissions); @@ -128,7 +128,7 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView { bundleView.renderView(nextViewPath);
} else if ("BundleGroup".equals(currentPath)) { - if (!nextViewPath.equals(currentBundleGroupViewId)) { + if (!nextViewPath.getCurrent().equals(currentBundleGroupViewId)) { // set new bundle detail currentBundleGroupViewId = nextViewPath.getCurrent(); bundleGroupView = new BundleGroupEditView(globalPermissions, Integer diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java index 9aa7a1e..0729815 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/AbstractBundleCreateWizard.java @@ -18,10 +18,13 @@ */ package org.rhq.enterprise.gui.coregui.client.bundle.create;
+import java.util.ArrayList; import java.util.HashMap; +import java.util.List;
import com.google.gwt.user.client.rpc.AsyncCallback;
+import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizard; @@ -32,10 +35,13 @@ import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity;
public abstract class AbstractBundleCreateWizard extends AbstractWizard {
- // the things we buildNodes up in the wizard + // the things we build up in the wizard private String recipe; private BundleVersion bundleVersion; + private String createInitialBundleVersionToken; + private String createInitialBundleVersionRecipe; private HashMap<String, Boolean> allBundleFilesStatus; // bundle file names with their upload status (true=they were uploaded) + private List<BundleGroup> initialBundleGroups = new ArrayList<BundleGroup>();
public String getRecipe() { return recipe; @@ -64,6 +70,35 @@ public abstract class AbstractBundleCreateWizard extends AbstractWizard { this.allBundleFilesStatus = allBundleFilesStatus; }
+ public String getCreateInitialBundleVersionToken() { + return createInitialBundleVersionToken; + } + + public void setCreateInitialBundleVersionToken(String createInitialBundleVersionToken) { + this.createInitialBundleVersionToken = createInitialBundleVersionToken; + } + + public String getCreateInitialBundleVersionRecipe() { + return createInitialBundleVersionRecipe; + } + + public void setCreateInitialBundleVersionRecipe(String createInitialBundleVersionRecipe) { + this.createInitialBundleVersionRecipe = createInitialBundleVersionRecipe; + } + + public boolean isInitialVersion() { + return ((null != createInitialBundleVersionToken) || (null != createInitialBundleVersionRecipe)); + } + + + public List<BundleGroup> getInitialBundleGroups() { + return initialBundleGroups; + } + + public void setInitialBundleGroups(List<BundleGroup> initialBundleGroups) { + this.initialBundleGroups = initialBundleGroups; + } + public void cancel() { final BundleVersion bv = getBundleVersion(); if (bv != null) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleCreateWizard.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleCreateWizard.java index 7bfd728..cfc568a 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleCreateWizard.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleCreateWizard.java @@ -19,22 +19,65 @@ package org.rhq.enterprise.gui.coregui.client.bundle.create;
import java.util.ArrayList; +import java.util.Set;
+import org.rhq.core.domain.authz.Permission; import org.rhq.enterprise.gui.coregui.client.components.wizard.WizardStep;
public class BundleCreateWizard extends AbstractBundleCreateWizard {
- public BundleCreateWizard() { + Set<Permission> globalPermissions; + + public BundleCreateWizard(Set<Permission> globalPermissions) { setWindowTitle(MSG.view_bundle_createWizard_windowTitle()); setTitle(MSG.view_bundle_createWizard_title());
+ //slightly increase the default dialog height so that we don't show the ugly scrollbar. + setDialogHeight(610); + + this.globalPermissions = globalPermissions; + ArrayList<WizardStep> steps = new ArrayList<WizardStep>(); steps.add(new BundleUploadDistroFileStep(this)); + steps.add(new BundleGroupsStep(this)); // this will be bypassed unless it's a new bundle steps.add(new BundleUploadDataStep(this)); steps.add(new BundleSummaryStep(this)); setSteps(steps); - - //slightly increase the default dialog height so that we don't show the ugly scrollbar. - setDialogHeight(610); } + + // @Override + // public void startWizard() { + // BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(); + // + // if (globalPermissions.contains(Permission.VIEW_BUNDLES)) { + // bundleServer.findBundleGroupsByCriteria(new BundleGroupCriteria(), + // new AsyncCallback<PageList<BundleGroup>>() { + // public void onSuccess(PageList<BundleGroup> result) { + // + // } + // + // public void onFailure(Throwable caught) { + // // TODO + // } + // }); + // + // } else { + // + // bundleServer.getCreateBundleGroups(new AsyncCallback<HashSet<BundleGroup>>() { + // public void onSuccess(HashSet<BundleGroup> result) { + // + // } + // + // public void onFailure(Throwable caught) { + // // TODO + // } + // }); + // + // + // // TODO Auto-generated method stub + // super.startWizard(); + // + // } + // + // } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java new file mode 100644 index 0000000..335f2d6 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleGroupsStep.java @@ -0,0 +1,64 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, 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.enterprise.gui.coregui.client.bundle.create; + +import java.util.Set; + +import com.smartgwt.client.widgets.Canvas; + +import org.rhq.core.domain.bundle.BundleGroup; +import org.rhq.enterprise.gui.coregui.client.bundle.group.BundleGroupSelector; +import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep; + +/** + * @author Jay Shaughnessy + */ +public class BundleGroupsStep extends AbstractWizardStep { + + private AbstractBundleCreateWizard wizard = null; + private BundleGroupSelector selector = null; + + public BundleGroupsStep(AbstractBundleCreateWizard wizard) { + this.wizard = wizard; + } + + public Canvas getCanvas() { + if (selector == null) { + selector = new BundleGroupSelector(); + } + return selector; + } + + public Set<BundleGroup> getSelectedBundleGroups() { + return selector.getSelectedItems(); + } + + public boolean nextPage() { + return true; + } + + public String getName() { + return MSG.common_title_bundleGroups(); + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleSummaryStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleSummaryStep.java index 5788b0b..04906d7 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleSummaryStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleSummaryStep.java @@ -24,6 +24,7 @@ import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.StaticTextItem;
+import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.components.wizard.AbstractWizardStep;
@@ -80,7 +81,18 @@ public class BundleSummaryStep extends AbstractWizardStep { } filesLabel.setValue(filesValueStr.toString());
- form.setFields(bundleTypeLabel, nameLabel, versionLabel, descriptionLabel, filesLabel); + StaticTextItem bundleGroupsLabel = new StaticTextItem("BundleGroups", MSG.common_title_bundleGroups()); + bundleGroupsLabel.setTitleVAlign(VerticalAlignment.TOP); + bundleGroupsLabel.setTitleAlign(Alignment.LEFT); + bundleGroupsLabel.setAlign(Alignment.LEFT); + bundleGroupsLabel.setWrap(false); + StringBuilder bundleGroupsValueStr = new StringBuilder(); + for (BundleGroup bundleGroup : wizard.getInitialBundleGroups()) { + bundleGroupsValueStr.append(bundleGroup.getName() + "<br/>\n"); + } + bundleGroupsLabel.setValue(bundleGroupsValueStr.toString()); + + form.setFields(bundleTypeLabel, nameLabel, versionLabel, descriptionLabel, filesLabel, bundleGroupsLabel);
return form; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java index 810b18f..a248efc 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/create/BundleUploadDistroFileStep.java @@ -264,27 +264,49 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { }
BundleGWTServiceAsync bundleServer = GWTServiceLookup.getBundleService(10 * 60 * 1000); // if upload takes more than 10m, you have other things to worry about - bundleServer.createBundleVersionViaURL(urlString, urlUserName, urlPassword, new AsyncCallback<BundleVersion>() { - @Override - public void onSuccess(BundleVersion result) { - CoreGUI.getMessageCenter().notify( - new Message(MSG.view_bundle_createWizard_createSuccessful(result.getName(), result.getVersion()), - Message.Severity.Info)); - wizard.setBundleVersion(result); - setButtonsDisableMode(false); - wizard.getView().incrementStep(); // go to the next step - } + bundleServer.createOrStoreBundleVersionViaURL(urlString, urlUserName, urlPassword, + new AsyncCallback<BundleVersion>() { + @Override + public void onSuccess(BundleVersion result) { + CoreGUI.getMessageCenter().notify( + new Message( + MSG.view_bundle_createWizard_createSuccessful(result.getName(), result.getVersion()), + Message.Severity.Info)); + wizard.setBundleVersion(result); + setButtonsDisableMode(false); + wizard.getView().incrementStep(); // go to the next step + }
- @Override - public void onFailure(Throwable caught) { - // Escape it, since it contains the URL, which the user entered. - String message = StringUtility.escapeHtml(caught.getMessage()); - wizard.getView().showMessage(message); - CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); - wizard.setBundleVersion(null); - setButtonsDisableMode(false); - } - }); + @Override + public void onFailure(Throwable caught) { + // This signals that the bundle does not yet exist + if (caught instanceof IllegalStateException) { + handleIllegalStateException((IllegalStateException) caught); + + } else { + // Escape it, since it contains the URL, which the user entered. + String message = StringUtility.escapeHtml(caught.getMessage()); + wizard.getView().showMessage(message); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); + wizard.setBundleVersion(null); + setButtonsDisableMode(false); + } + } + }); + } + + private void handleIllegalStateException(IllegalStateException e) { + String token = e.getMessage(); + if (null == token || token.isEmpty()) { + wizard.getView().showMessage("IllegalStateException: Unexpected failure creating bundle version."); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), e); + wizard.setBundleVersion(null); + setButtonsDisableMode(false); + } + + wizard.setCreateInitialBundleVersionToken(token); + setButtonsDisableMode(false); + wizard.getView().incrementStep(); // go to the next step }
private void processUpload() { @@ -314,6 +336,10 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep { setButtonsDisableMode(false); } }); + } else if (null != uploadDistroForm.getCreateInitialBundleVersionToken()) { + handleIllegalStateException(new IllegalStateException( + uploadDistroForm.getCreateInitialBundleVersionToken())); + } else { String errorMessage = uploadDistroForm.getUploadError(); handleUploadError(errorMessage, true); @@ -347,11 +373,23 @@ public class BundleUploadDistroFileStep extends AbstractWizardStep {
@Override public void onFailure(Throwable caught) { - wizard.getView().showMessage(caught.getMessage()); - CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); - wizard.setBundleVersion(null); - wizard.setRecipe(""); - setButtonsDisableMode(false); + boolean handled = false; + String message = caught.getMessage(); + + if (message.contains("PermissionException") && message.contains("initial")) { + handled = true; + wizard.setCreateInitialBundleVersionRecipe(wizard.getRecipe()); + setButtonsDisableMode(false); + wizard.getView().incrementStep(); // go to the next step + } + + if (!handled) { + wizard.getView().showMessage(caught.getMessage()); + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); + wizard.setBundleVersion(null); + wizard.setRecipe(""); + setButtonsDisableMode(false); + } } }); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java index 50ca139..296a070 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java @@ -136,7 +136,7 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> { addTableAction(MSG.common_button_new(), null, new AbstractTableAction( (hasAuth) ? TableActionEnablement.ALWAYS : TableActionEnablement.NEVER) { public void executeAction(ListGridRecord[] selection, Object actionValue) { - new BundleCreateWizard().startWizard(); + new BundleCreateWizard(permissions).startWizard(); // we can refresh the table buttons immediately since the wizard is a dialog, the // user can't access enabled buttons anyway. BundlesListView.this.refreshTableInfo(); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java index fd0815f9..04fcbf0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/upload/BundleDistributionFileUploadForm.java @@ -25,6 +25,7 @@ import org.rhq.enterprise.gui.coregui.client.CoreGUI; public class BundleDistributionFileUploadForm extends FileUploadForm {
private int bundleVersionId; + private String createInitialBundleVersionToken;
public BundleDistributionFileUploadForm(boolean showUploadButton) {
@@ -34,8 +35,8 @@ public class BundleDistributionFileUploadForm extends FileUploadForm { }
/** - * If this component successfully uploaded a bundle distribution file, this will return - * the new bundle version's ID. Otherwise, 0 is returned. + * If this component successfully uploaded a bundle distribution file and created the bundle version, this + * will return the new bundle version's ID. Otherwise, 0 is returned. * * @return the new bundle version ID */ @@ -43,13 +44,40 @@ public class BundleDistributionFileUploadForm extends FileUploadForm { return this.bundleVersionId; }
+ /** + * If this component uploaded a bundle distribution file but failed to create the bundle version + * due to an IllegalStateException (signaling bundle not found), this will return the token necessary to then call + * createInitialBundleVersionViaToken(). Otherwise, null is returned. + * + * @return the token required for a a subsequent call to createInitialBundleVersionViaToken(). + */ + public String getCreateInitialBundleVersionToken() { + return this.createInitialBundleVersionToken; + } + protected boolean processSubmitCompleteResults(String submitCompleteEventResults) { - bundleVersionId = parseIdFromResponse(submitCompleteEventResults); + bundleVersionId = parseResponse(submitCompleteEventResults); return (bundleVersionId > 0); }
- private int parseIdFromResponse(String results) { - String successMsgPrefix = "success ["; // the upload servlet will respond with "success [bundleVersionId]" on success + private int parseResponse(String results) { + // the upload servlet will respond with "BundleNotFoundException [createInitialBundleVersionToken]" to indicate + // that the BV create failed because the bundle does not yet exist. + String IllegalStateMsgPrefix = "IllegalStateException ["; + int startIllegalStateMsgPrefix = results.indexOf(IllegalStateMsgPrefix); + if (startIllegalStateMsgPrefix >= 0) { + int endIllegalStateMsgPrefix = startIllegalStateMsgPrefix + IllegalStateMsgPrefix.length(); + int startIllegalStateMsgPostfix = results.indexOf(']', endIllegalStateMsgPrefix); + if (startIllegalStateMsgPostfix < 0) { + return 0; // this should never happen, we should always have the ending "]" bracket + } + this.createInitialBundleVersionToken = results.substring(endIllegalStateMsgPrefix, + startIllegalStateMsgPostfix); + return 0; + } + + // the upload servlet will respond with "success [bundleVersionId]" on success + String successMsgPrefix = "success ["; int startSuccessMsgPrefix = results.indexOf(successMsgPrefix); if (startSuccessMsgPrefix < 0) { return 0; // must mean it wasn't a success - results is probably an error message diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java index 3c73e17..4e80e6c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java @@ -20,6 +20,7 @@ package org.rhq.enterprise.gui.coregui.client.gwt;
import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet;
import com.google.gwt.user.client.rpc.RemoteService;
@@ -47,7 +48,10 @@ public interface BundleGWTService extends RemoteService {
ResourceTypeBundleConfiguration getResourceTypeBundleConfiguration(int compatGroupId) throws RuntimeException;
- BundleVersion createBundleVersionViaURL(String url, String username, String password) throws RuntimeException; + BundleVersion createOrStoreBundleVersionViaURL(String url, String username, String password) + throws RuntimeException; + + BundleVersion createInitialBundleVersionViaRecipe(int[] bundleGroupIds, String recipe) throws RuntimeException;
BundleVersion createBundleVersionViaRecipe(String recipe) throws RuntimeException;
@@ -109,4 +113,6 @@ public interface BundleGWTService extends RemoteService {
BundleGroup updateBundleGroup(BundleGroup bundleGroup) throws RuntimeException;
+ HashSet<BundleGroup> getCreateBundleGroups() throws RuntimeException; + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java index 0184f9a..91043c6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleDistributionFileUploadServlet.java @@ -51,8 +51,12 @@ public class BundleDistributionFileUploadServlet extends FileUploadServlet { File file = files.values().iterator().next();
BundleManagerLocal bundleManager = LookupUtil.getBundleManager(); - BundleVersion bundleVersion = bundleManager.createBundleVersionViaFile(subject, file); + BundleVersion bundleVersion = bundleManager.createOrStoreBundleVersionViaFile(subject, file); successMsg = "success [" + bundleVersion.getId() + "]"; + + } catch (IllegalStateException e) { + writeExceptionResponse(response, "IllegalStateException [" + e.getMessage() + "]", e); // clients will look for this string! + return; } catch (Exception e) { writeExceptionResponse(response, "Failed to upload bundle distribution file", e); // clients will look for this string! return; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java index 40955d4..ce229b9 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java @@ -20,7 +20,10 @@ package org.rhq.enterprise.gui.coregui.server.gwt;
import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet;
+import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.bundle.Bundle; import org.rhq.core.domain.bundle.BundleDeployment; import org.rhq.core.domain.bundle.BundleDestination; @@ -39,6 +42,7 @@ import org.rhq.core.domain.criteria.BundleFileCriteria; import org.rhq.core.domain.criteria.BundleGroupCriteria; import org.rhq.core.domain.criteria.BundleResourceDeploymentCriteria; import org.rhq.core.domain.criteria.BundleVersionCriteria; +import org.rhq.core.domain.criteria.RoleCriteria; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTService; import org.rhq.enterprise.gui.coregui.server.util.SerialUtility; @@ -63,10 +67,12 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override - public BundleVersion createBundleVersionViaURL(String url, String username, String password) throws RuntimeException { + public BundleVersion createOrStoreBundleVersionViaURL(String url, String username, String password) + throws RuntimeException { try { - BundleVersion results = bundleManager.createBundleVersionViaURL(getSessionSubject(), url, username, password); - return SerialUtility.prepare(results, "createBundleVersionViaURL"); + BundleVersion results = bundleManager.createBundleVersionViaURL(getSessionSubject(), url, username, + password); + return SerialUtility.prepare(results, "createOrStoreBundleVersionViaURL"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } @@ -93,13 +99,25 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override + public BundleVersion createInitialBundleVersionViaRecipe(int[] bundleGroupIds, String recipe) + throws RuntimeException { + try { + BundleVersion results = bundleManager.createInitialBundleVersionViaRecipe(getSessionSubject(), + bundleGroupIds, recipe); + return SerialUtility.prepare(results, "createInitialBundleVersionViaRecipe"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override public BundleDeployment createBundleDeployment(int bundleVersionId, int bundleDestinationId, String description, Configuration configuration, boolean enforcePolicy, int enforcementInterval, boolean pinToBundle) throws RuntimeException {
try { BundleDeployment result = bundleManager.createBundleDeployment(getSessionSubject(), bundleVersionId, - bundleDestinationId, description, configuration); + bundleDestinationId, description, configuration); return SerialUtility.prepare(result, "createBundleDeployment"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); @@ -112,7 +130,7 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund
try { BundleDestination result = bundleManager.createBundleDestination(getSessionSubject(), bundleId, name, - description, destBaseDirName, deployDir, groupId); + description, destBaseDirName, deployDir, groupId); return SerialUtility.prepare(result, "createBundleDestination"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); @@ -225,7 +243,7 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund boolean isCleanDeployment) throws RuntimeException { try { BundleDeployment result = bundleManager.scheduleRevertBundleDeployment(getSessionSubject(), - bundleDeploymentId, deploymentDescription, isCleanDeployment); + bundleDeploymentId, deploymentDescription, isCleanDeployment); return SerialUtility.prepare(result, "scheduleRevertBundleDeployment"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); @@ -339,4 +357,30 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund } }
+ @Override + public HashSet<BundleGroup> getCreateBundleGroups() throws RuntimeException { + try { + RoleCriteria c = new RoleCriteria(); + c.addFilterSubjectId(getSessionSubject().getId()); + ArrayList<Permission> l = new ArrayList<Permission>(1); + l.add(Permission.CREATE_BUNDLES_IN_GROUP); + c.addFilterPermissions(l); + c.fetchBundleGroups(true); + + PageList<Role> roles = LookupUtil.getRoleManager().findRolesByCriteria( + LookupUtil.getSubjectManager().getOverlord(), c); + + HashSet<BundleGroup> result = new HashSet<BundleGroup>(); + for (Role role : roles) { + for (BundleGroup bundleGroup : role.getBundleGroups()) { + result.add(bundleGroup); + } + } + + return SerialUtility.prepare(result, "getCreateBundleGroups"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + } diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java index 43e1bd9..b85e650 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java @@ -1281,7 +1281,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { final BundleType type = createBundleType(name); final String recipe = "deploy -f " + TEST_PREFIX + ".zip -d @@ test.path @@"; final BundleVersion bundleVerison = bundleManager.createBundleAndBundleVersion(overlord, fullName, - "description", type.getId(), 0, fullName, fullName + "-desc", "3.0", recipe); + "description", type.getId(), null, fullName, fullName + "-desc", "3.0", recipe); assertNotNull(bundleVerison);
// find the previously created bundle @@ -1311,7 +1311,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { final String fullName = TEST_PREFIX + "-bundle-" + name; final String recipe = "deploy -f " + TEST_PREFIX + ".zip -d @@ test.path @@"; final BundleVersion bundleVerison = bundleManager.createBundleAndBundleVersion(overlord, fullName, - "description", bundle.getBundleType().getId(), 0, fullName, fullName + "-desc", "3.0", recipe); + "description", bundle.getBundleType().getId(), null, fullName, fullName + "-desc", "3.0", recipe);
// find the newly created bundle BundleCriteria c = new BundleCriteria(); @@ -2091,7 +2091,8 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
private Bundle createBundle(Subject subject, String name, BundleType bt, int bundleGroupId) throws Exception { final String fullName = TEST_PREFIX + "-bundle-" + name; - Bundle b = bundleManager.createBundle(subject, fullName, fullName + "-desc", bt.getId(), bundleGroupId); + Bundle b = bundleManager.createBundle(subject, fullName, fullName + "-desc", bt.getId(), + new int[] { bundleGroupId });
assert b.getId() > 0; assert b.getName().endsWith(fullName); diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java index 1d6b49a..bfe36f6 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java @@ -697,7 +697,7 @@ public class ResourceMetadataManagerBeanTest extends MetadataBeanTest { BundleType bundleType = bundleMgr.getBundleType(subjectMgr.getOverlord(), bundleTypeName); assertNotNull("Cannot create bundle. Unable to find bundle type for [name: " + bundleTypeName + "]", bundleType); Bundle bundle = bundleMgr.createBundle(subjectMgr.getOverlord(), bundleName, "test bundle: " + bundleName, - bundleType.getId(), 0); + bundleType.getId(), null);
assertNotNull("Failed create bundle for [name: " + bundleName + "]", bundle); } diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java index 01c58a0..7e66087 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java @@ -260,7 +260,7 @@ public class TagManagerBeanTest extends AbstractEJB3Test { private Bundle createBundle() throws Exception { ResourceType resourceType = SessionTestHelper.createNewResourceType(em); BundleType bundleType = bundleManager.createBundleType(overlord, getRandomString(), resourceType.getId()); - return bundleManager.createBundle(overlord, getRandomString(), getRandomString(), bundleType.getId(), 0); + return bundleManager.createBundle(overlord, getRandomString(), getRandomString(), bundleType.getId(), null); }
private BundleVersion createBundleVersion() throws Exception { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java index 6b4a890..b8e16f0 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java @@ -215,7 +215,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - public Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int bundleGroupId) + public Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int[] bundleGroupIds) throws Exception { if (null == name || "".equals(name.trim())) { throw new IllegalArgumentException("Invalid bundleName: " + name); @@ -226,15 +226,17 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot throw new IllegalArgumentException("Invalid bundleTypeId: " + bundleTypeId); }
- BundleGroup bundleGroup = null; - if (bundleGroupId > 0) { - bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); + bundleGroupIds = (null != bundleGroupIds) ? bundleGroupIds : new int[0]; + List<BundleGroup> bundleGroups = new ArrayList<BundleGroup>(bundleGroupIds.length); + for (int bundleGroupId : bundleGroupIds) { + BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); if (null == bundleGroup) { throw new IllegalArgumentException("Invalid bundleGroupId: " + bundleGroupId); } + bundleGroups.add(bundleGroup); }
- checkCreateInitialBundleVersionAuthz(subject, bundleGroupId); + checkCreateInitialBundleVersionAuthz(subject, bundleGroupIds);
// create and add the required Repo. the Repo is a detached object which helps in its eventual removal. Repo repo = new Repo(name); @@ -263,7 +265,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot log.info("Creating bundle: " + bundle); entityManager.persist(bundle);
- if (null != bundleGroup) { + for (BundleGroup bundleGroup : bundleGroups) { bundleGroup.addBundle(bundle); }
@@ -475,8 +477,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override public BundleVersion createBundleAndBundleVersion(Subject subject, String bundleName, String bundleDescription, - int bundleTypeId, int bundleGroupId, String bundleVersionName, String bundleVersionDescription, String version, - String recipe) throws Exception { + int bundleTypeId, int[] bundleGroupIds, String bundleVersionName, String bundleVersionDescription, + String version, String recipe) throws Exception {
// first see if the bundle exists or not; if not, create one BundleCriteria criteria = new BundleCriteria(); @@ -488,7 +490,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot PageList<Bundle> bundles = findBundlesByCriteria(subject, criteria); Bundle bundle; if (bundles.getTotalSize() == 0) { - bundle = createBundle(subject, bundleName, bundleDescription, bundleTypeId, bundleGroupId); + bundle = createBundle(subject, bundleName, bundleDescription, bundleTypeId, bundleGroupIds); } else { bundle = bundles.get(0); } @@ -572,25 +574,27 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override + @TransactionAttribute(TransactionAttributeType.NEVER) public BundleVersion createBundleVersionViaRecipe(Subject subject, String recipe) throws Exception {
- return createBundleVersionViaRecipeImpl(subject, recipe, false, 0); + return createBundleVersionViaRecipeImpl(subject, recipe, false, null); }
@Override - public BundleVersion createInitialBundleVersionViaRecipe(Subject subject, int bundleGroupId, String recipe) + @TransactionAttribute(TransactionAttributeType.NEVER) + public BundleVersion createInitialBundleVersionViaRecipe(Subject subject, int[] bundleGroupIds, String recipe) throws Exception {
- return createBundleVersionViaRecipeImpl(subject, recipe, true, bundleGroupId); + return createBundleVersionViaRecipeImpl(subject, recipe, true, bundleGroupIds); }
private BundleVersion createBundleVersionViaRecipeImpl(Subject subject, String recipe, - boolean mustBeInitialVersion, int initialBundleGroupId) throws Exception { + boolean mustBeInitialVersion, int[] initialBundleGroupIds) throws Exception {
BundleServerPluginManager manager = BundleManagerHelper.getPluginContainer().getBundleServerPluginManager(); BundleDistributionInfo info = manager.parseRecipe(recipe); BundleVersion bundleVersion = createBundleVersionViaDistributionInfo(subject, info, mustBeInitialVersion, - initialBundleGroupId); + initialBundleGroupIds);
return bundleVersion; } @@ -599,24 +603,39 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot @TransactionAttribute(TransactionAttributeType.NEVER) public BundleVersion createBundleVersionViaFile(Subject subject, File distributionFile) throws Exception {
- return createBundleVersionViaFileImpl(subject, distributionFile, false, 0); + return createBundleVersionViaFileImpl(subject, distributionFile, false, null); + } + + @Override + @TransactionAttribute(TransactionAttributeType.NEVER) + public BundleVersion createOrStoreBundleVersionViaFile(Subject subject, File distributionFile) throws Exception { + try { + return createBundleVersionViaFileImpl(subject, distributionFile, false, null); + + } catch (PermissionException e) { + if (null != e.getCause() && e.getCause() instanceof BundleNotFoundException) { + throw new IllegalStateException("[" + distributionFile.getName() + "]"); + } else { + throw e; + } + } }
@Override @TransactionAttribute(TransactionAttributeType.NEVER) - public BundleVersion createInitialBundleVersionViaFile(Subject subject, int bundleGroupId, File distributionFile) + public BundleVersion createInitialBundleVersionViaFile(Subject subject, int[] bundleGroupIds, File distributionFile) throws Exception {
- return createBundleVersionViaFileImpl(subject, distributionFile, true, bundleGroupId); + return createBundleVersionViaFileImpl(subject, distributionFile, true, bundleGroupIds); }
private BundleVersion createBundleVersionViaFileImpl(Subject subject, File distributionFile, - boolean mustBeInitialVersion, int initialBundleGroupId) throws Exception { + boolean mustBeInitialVersion, int[] initialBundleGroupIds) throws Exception {
BundleServerPluginManager manager = BundleManagerHelper.getPluginContainer().getBundleServerPluginManager(); BundleDistributionInfo info = manager.processBundleDistributionFile(distributionFile); BundleVersion bundleVersion = createBundleVersionViaDistributionInfo(subject, info, mustBeInitialVersion, - initialBundleGroupId); + initialBundleGroupIds);
return bundleVersion; } @@ -625,25 +644,25 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot @TransactionAttribute(TransactionAttributeType.NEVER) public BundleVersion createBundleVersionViaByteArray(Subject subject, byte[] fileBytes) throws Exception {
- return createBundleVersionViaByteArrayImpl(subject, fileBytes, false, 0); + return createBundleVersionViaByteArrayImpl(subject, fileBytes, false, null); }
@Override @TransactionAttribute(TransactionAttributeType.NEVER) - public BundleVersion createInitialBundleVersionViaByteArray(Subject subject, int bundleGroupId, byte[] fileBytes) + public BundleVersion createInitialBundleVersionViaByteArray(Subject subject, int[] bundleGroupIds, byte[] fileBytes) throws Exception {
- return createBundleVersionViaByteArrayImpl(subject, fileBytes, true, bundleGroupId); + return createBundleVersionViaByteArrayImpl(subject, fileBytes, true, bundleGroupIds); }
private BundleVersion createBundleVersionViaByteArrayImpl(Subject subject, byte[] fileBytes, - boolean mustBeInitialVersion, int bundleGroupId) throws Exception { + boolean mustBeInitialVersion, int[] bundleGroupIds) throws Exception {
File tmpFile = File.createTempFile("bundleDistroBits", ".zip"); try { StreamUtil.copy(new ByteArrayInputStream(fileBytes), new FileOutputStream(tmpFile)); BundleVersion bundleVersion = createBundleVersionViaFileImpl(subject, tmpFile, mustBeInitialVersion, - bundleGroupId); + bundleGroupIds); return bundleVersion; } finally { if (tmpFile != null) { @@ -664,25 +683,27 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot public BundleVersion createBundleVersionViaURL(Subject subject, String distributionFileUrl, String username, String password) throws Exception {
- return createBundleVersionViaURLImpl(subject, distributionFileUrl, username, password, false, 0); + return createBundleVersionViaURLImpl(subject, distributionFileUrl, username, password, false, null); }
@Override - public BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl) - throws Exception { + @TransactionAttribute(TransactionAttributeType.NEVER) + public BundleVersion createInitialBundleVersionViaURL(Subject subject, int[] bundleGroupIds, + String distributionFileUrl) throws Exception {
- return createInitialBundleVersionViaURL(subject, bundleGroupId, distributionFileUrl, null, null); + return createInitialBundleVersionViaURL(subject, bundleGroupIds, distributionFileUrl, null, null); }
@Override - public BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, + @TransactionAttribute(TransactionAttributeType.NEVER) + public BundleVersion createInitialBundleVersionViaURL(Subject subject, int[] bundleGroupIds, String distributionFileUrl, String username, String password) throws Exception {
- return createBundleVersionViaURLImpl(subject, distributionFileUrl, username, password, true, bundleGroupId); + return createBundleVersionViaURLImpl(subject, distributionFileUrl, username, password, true, bundleGroupIds); }
public BundleVersion createBundleVersionViaURLImpl(Subject subject, String distributionFileUrl, String username, - String password, boolean mustBeInitialVersion, int initialBundleGroupId) throws Exception { + String password, boolean mustBeInitialVersion, int[] initialBundleGroupIds) throws Exception { File file = null; try { file = downloadFile(distributionFileUrl, username, password); @@ -690,7 +711,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot log.debug("Copied [" + file.length() + "] bytes from [" + distributionFileUrl + "] into [" + file.getPath() + "]");
- return createBundleVersionViaFileImpl(subject, file, mustBeInitialVersion, initialBundleGroupId); + return createBundleVersionViaFileImpl(subject, file, mustBeInitialVersion, initialBundleGroupIds); } finally { if (file != null) { file.delete(); @@ -698,6 +719,35 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot } }
+ @Override + @TransactionAttribute(TransactionAttributeType.NEVER) + public BundleVersion createOrStoreBundleVersionViaURL(Subject subject, String distributionFileUrl, String username, + String password) throws Exception { + + File file = null; + boolean deleteFile = true; + try { + file = downloadFile(distributionFileUrl, username, password); + + log.debug("Copied [" + file.length() + "] bytes from [" + distributionFileUrl + "] into [" + file.getPath() + + "]"); + + return createBundleVersionViaFileImpl(subject, file, false, null); + + } catch (PermissionException e) { + if (null != e.getCause() && e.getCause() instanceof BundleNotFoundException) { + deleteFile = false; + throw new IllegalStateException("[" + file.getName() + "]"); + } else { + throw e; + } + } finally { + if (deleteFile && file != null) { + file.delete(); + } + } + } + private File downloadFile(String fileUrl, String username, String password) throws IOException, URISyntaxException { URL url = new URL(fileUrl);
@@ -741,7 +791,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
private BundleVersion createBundleVersionViaDistributionInfo(Subject subject, BundleDistributionInfo info, - boolean mustBeInitialVersion, Integer initialBundleGroupId) throws Exception { + boolean mustBeInitialVersion, int[] initialBundleGroupIds) throws Exception {
BundleType bundleType = bundleManager.getBundleType(subject, info.getBundleTypeName()); String bundleName = info.getRecipeParseResults().getBundleMetadata().getBundleName(); @@ -768,7 +818,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
if (isInitialVersion) { bundle = bundleManager.createBundle(subject, bundleName, bundleDescription, bundleType.getId(), - initialBundleGroupId); + initialBundleGroupIds); createdBundle = true; } else { bundle = bundles.get(0); @@ -1942,6 +1992,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot } }
+ @SuppressWarnings("unused") private void safeClose(OutputStream os) { if (null != os) { try { @@ -2071,11 +2122,10 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG * </pre> * @param subject - * @param bundleGroupId null or 0 for unassigned initial bundle version creation + * @param bundleGroupIds null or 0 length for unassigned initial bundle version creation * @throws PermissionException */ - private void checkCreateInitialBundleVersionAuthz(Subject subject, Integer bundleGroupId) - throws PermissionException { + private void checkCreateInitialBundleVersionAuthz(Subject subject, int[] bundleGroupIds) throws PermissionException { Set<Permission> globalPerms = authorizationManager.getExplicitGlobalPermissions(subject); boolean hasGlobalCreateBundles = globalPerms.contains(Permission.CREATE_BUNDLES);
@@ -2083,28 +2133,32 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot return; }
- if (null == bundleGroupId || bundleGroupId.intValue() <= 0) { + if (null == bundleGroupIds || bundleGroupIds.length == 0) { String msg = "Subject [" + subject.getName() - + "] requires Global CREATE_BUNDLES and VIEW_BUNDLES to create unsassigned initial bundle version."; - throw new PermissionException(msg); + + "] requires Global CREATE_BUNDLES and VIEW_BUNDLES to create unassigned initial bundle version."; + throw new PermissionException(msg, new BundleNotFoundException()); // set the cause to BNFE, this is helpful to some callers }
- if (hasGlobalCreateBundles) { - if (authorizationManager.canViewBundleGroup(subject, bundleGroupId)) { - return; + for (int bundleGroupId : bundleGroupIds) { + boolean authzPassed; + if (hasGlobalCreateBundles) { + authzPassed = authorizationManager.canViewBundleGroup(subject, bundleGroupId); + + } else { + authzPassed = authorizationManager.hasBundleGroupPermission(subject, + Permission.CREATE_BUNDLES_IN_GROUP, bundleGroupId); } - } else { - if (authorizationManager.hasBundleGroupPermission(subject, Permission.CREATE_BUNDLES_IN_GROUP, - bundleGroupId)) { - return; + + if (!authzPassed) { + String msg = "Subject [" + + subject.getName() + + "] requires either Global.CREATE_BUNDLES + BundleGroup.VIEW_BUNDLES_IN_GROUP, or BundleGroup.CREATE_BUNDLES_IN_GROUP, to create or update a bundle in bundle group [" + + bundleGroupIds + "]."; + throw new PermissionException(msg); } }
- String msg = "Subject [" - + subject.getName() - + "] requires either Global.CREATE_BUNDLES + BundleGroup.VIEW_BUNDLES_IN_GROUP, or BundleGroup.CREATE_BUNDLES_IN_GROUP, to create or update a bundle in bundle group [" - + bundleGroupId + "]."; - throw new PermissionException(msg); + return; }
/** @@ -2347,13 +2401,12 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot public BundleGroup updateBundleGroup(Subject subject, BundleGroup bundleGroup) throws Exception { BundleGroup attachedBundleGroup = entityManager.find(BundleGroup.class, bundleGroup.getId()); if (attachedBundleGroup == null) { - throw new IllegalStateException("Cannot update " + bundleGroup + throw new IllegalArgumentException("Cannot update " + bundleGroup + ", because no bundle group exists with id [" + bundleGroup.getId() + "]."); }
// First update the simple fields and the permissions. attachedBundleGroup.setName(bundleGroup.getName()); - attachedBundleGroup.setDescription(bundleGroup.getDescription());
Set<Bundle> newBundles = bundleGroup.getBundles(); if (newBundles != null) { @@ -2379,4 +2432,19 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot return attachedBundleGroup; }
+ @Override + @TransactionAttribute(TransactionAttributeType.NEVER) + public BundleVersion createInitialBundleVersionViaToken(Subject subject, int[] bundleGroupIds, String token) + throws Exception { + + File distributionFile = new File(System.getProperty("java.io.tmpdir"), token); + if (!distributionFile.isFile()) { + throw new IllegalArgumentException("Token did not result in valid file [" + + distributionFile.getAbsolutePath() + "]"); + } + + return createInitialBundleVersionViaFile(subject, bundleGroupIds, distributionFile); + + } + } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java index 21bafd6..64365c4 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.bundle;
+import java.io.File; import java.util.HashMap; import java.util.Map;
@@ -78,10 +79,10 @@ public interface BundleManagerLocal extends BundleManagerRemote { * @param name not null or empty * @param description optional long description of the bundle * @param bundleTypeId valid bundleType - * @param bundleGroupId bundle group, existing bundle group for bundle assignment, or 0 for unassigned + * @param bundleGroupIds existing bundle groups for initial bundle assignment, null or 0 length for unassigned * @return the persisted Bundle (id is assigned) */ - Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int bundleGroupId) + Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int[] bundleGroupIds) throws Exception;
/** @@ -100,15 +101,15 @@ public interface BundleManagerLocal extends BundleManagerRemote { * @param bundleName name of the bundle to use (if not found, it will be created) * @param bundleDescription optional long description of the bundle * @param bundleTypeId the bundle type for the new bundle (if it is created) for which this will be the first version - * @param bundleGroupId the bundle group for the new bundle (if it is created) for which this will be the first version. 0 to leave unassigned. + * @param bundleGroupIds the bundle groups for the new bundle (if it is created) for which this will be the first version. null to leave unassigned. * @param bundleVersionName name of the bundle version * @param bundleVersionDescription optional long description of the bundle version * @param version optional. If not supplied set to 1.0 for first version, or incremented (as best as possible) for subsequent version * @return the persisted BundleVersion (id is assigned) */ BundleVersion createBundleAndBundleVersion(Subject subject, String bundleName, String bundleDescription, - int bundleTypeId, int bundleGroupId, String bundleVersionName, String bundleVersionDescription, String version, - String recipe) throws Exception; + int bundleTypeId, int[] bundleGroupIds, String bundleVersionName, String bundleVersionDescription, + String version, String recipe) throws Exception;
/** * Internal use only, test entry point @@ -270,4 +271,56 @@ public interface BundleManagerLocal extends BundleManagerRemote { void _finalizePurge(Subject subject, BundleDeployment bundleDeployment, Map<BundleResourceDeployment, String> failedToPurge) throws Exception;
+ /** + * Like {@link #createBundleVersionViaFile(Subject, File)} with one additional feature. + * This method exists solely to support the GUI's wizard workflow which always first tries to create a bundle + * version for an existing bundle, because it does not know whether this is an initial bundle version (only + * the server can figure that out after it cracks open the bundle distribution, parses the recipe, and + * looks for the bundle). If this is an initialBundleVersion this method does two things. First, it stores the + * distribution file as a temp file, this is done to avoid having to upload the file a second time. Second, it + * throws IllegalStateException with special message text, a token that can be sent back to + * {@link #createInitialBundleVersionViaToken(Subject, int[], String)}. + */ + BundleVersion createOrStoreBundleVersionViaFile(Subject subject, File distributionFile) throws Exception; + + /** + * Like {@link #createBundleVersionViaURL(Subject, String, String, String)} with one additional feature. + * This method exists solely to support the GUI's wizard workflow which always first tries to create a bundle + * version for an existing bundle, because it does not know whether this is an initial bundle version (only + * the server can figure that out after it cracks open the bundle distribution, parses the recipe, and + * looks for the bundle). If this is an initialBundleVersion this method does two things. First, it stores the + * distribution file as a temp file, this is done to avoid having to upload the file a second time. Second, it + * throws IllegalStateException with special message text, a token that can be sent back to + * {@link #createInitialBundleVersionViaToken(Subject, int[], String)}. + */ + BundleVersion createOrStoreBundleVersionViaURL(Subject subject, String distributionFileUrl, String username, + String password) throws Exception; + + /** + * This method exists solely to support the GUI's wizard workflow which always first tries to create a bundle + * version for an existing bundle, because it does not know whether this is an initial bundle version (only + * the server can figure that out after it cracks open the bundle distribution, parses the recipe, and + * looks for the bundle). It works in conjunction with {@link #createOrStoreBundleVersionViaFile(Subject, File)} or + * {@link #createOrStoreBundleVersionViaURL(Subject, String, String, String)}. + * <p/> + * This method will use the supplied token to access the distribution file. It assumes this is a new bundle and + * is responsible for creating the bundle as well as the bundle version. The caller can indicate which bundle + * groups the new bundle should be assigned to. If bundleGroupId is null, then the new bundle will not be + * associated with any bundle group - this is only allowed if the caller has the permission Global.VIEW_BUNDLES. + * <pre> + * Required Permissions: Either: + * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES + * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG + * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG + * </pre> + * @param subject user that must have proper permissions + * @param bundleGroupIds identifies the bundle groups that the new bundle will be associated with; null or zero + * length to leave unassigned. + * @param token the token used to identify the distribution file stashed as a temp file. + * @return the persisted BundleVersion with a lot of the internal relationships filled in to help the caller + * understand all that this method did. + */ + BundleVersion createInitialBundleVersionViaToken(Subject subject, int[] bundleGroupIds, String token) + throws Exception; + } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java index 3eeb3f1..b3d849a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java @@ -242,9 +242,9 @@ public interface BundleManagerRemote {
/** * Like #createBundleVersionViaRecipe except this method will assume this is a new bundle and is responsible - * for creating the bundle as well as the bundle version. The caller can indicate which bundle group the new bundle + * for creating the bundle as well as the bundle version. The caller can indicate which bundle groups the new bundle * should be assigned to. - * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only + * If bundleGroupIds is null, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. * <pre> * Required Permissions: Either: @@ -253,12 +253,13 @@ public interface BundleManagerRemote { * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG * </pre> * @param subject user that must have proper permissions - * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group + * @param bundleGroupIds identifies the bundle groups that the new bundle will be associated with; null or zero + * length to leave unassigned. * @param recipe the recipe that defines the bundle version to be created * @return the persisted BundleVersion with alot of the internal relationships filled in to help the caller * understand all that this method did. */ - BundleVersion createInitialBundleVersionViaRecipe(Subject subject, int bundleGroupId, String recipe) + BundleVersion createInitialBundleVersionViaRecipe(Subject subject, int[] bundleGroupIds, String recipe) throws Exception;
/** @@ -285,9 +286,9 @@ public interface BundleManagerRemote {
/** * Like #createBundleVersionViaFile except this method will assume this is a new bundle and is responsible - * for creating the bundle as well as the bundle version. The caller can indicate which bundle group the new bundle + * for creating the bundle as well as the bundle version. The caller can indicate which bundle groups the new bundle * should be assigned to. - * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only + * If bundleGroupIds is null, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. * <pre> * Required Permissions: Either: @@ -296,13 +297,14 @@ public interface BundleManagerRemote { * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG * </pre> * @param subject user that must have proper permissions - * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group + * @param bundleGroupIds identifies the bundle groups that the new bundle will be associated with; null or zero + * length to leave unassigned. * @param distributionFile a local Bundle Distribution file. It must be read accessible by the RHQ server process. * @return the persisted BundleVersion with alot of the internal relationships filled in to help the caller * understand all that this method did. Bundle files specifically are returned. * @throws Exception */ - BundleVersion createInitialBundleVersionViaFile(Subject subject, int bundleGroupId, File distributionFile) + BundleVersion createInitialBundleVersionViaFile(Subject subject, int[] bundleGroupIds, File distributionFile) throws Exception;
/** @@ -329,9 +331,9 @@ public interface BundleManagerRemote {
/** * Like #createBundleVersionViaByteArray except this method will assume this is a new bundle and is responsible - * for creating the bundle as well as the bundle version. The caller can indicate which bundle group the new bundle + * for creating the bundle as well as the bundle version. The caller can indicate which bundle groups the new bundle * should be assigned to. - * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only + * If bundleGroupIds is null, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. * <pre> * Required Permissions: Either: @@ -340,13 +342,14 @@ public interface BundleManagerRemote { * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG * </pre> * @param subject user that must have proper permissions - * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group + * @param bundleGroupIds identifies the bundle groups that the new bundle will be associated with; null or zero + * length to leave unassigned. * @param fileBytes the file bits that make up the entire bundle distribution file * @return the persisted BundleVersion with a lot of the internal relationships filled in to help the caller * understand all that this method did. Bundle files specifically are returned. * @throws Exception */ - BundleVersion createInitialBundleVersionViaByteArray(Subject subject, int bundleGroupId, byte[] fileBytes) + BundleVersion createInitialBundleVersionViaByteArray(Subject subject, int[] bundleGroupIds, byte[] fileBytes) throws Exception;
/** @@ -377,9 +380,9 @@ public interface BundleManagerRemote {
/** * Like #createBundleVersionViaURL except this method will assume this is a new bundle and is responsible - * for creating the bundle as well as the bundle version. The caller can indicate which bundle group the new bundle + * for creating the bundle as well as the bundle version. The caller can indicate which bundle groups the new bundle * should be assigned to. - * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only + * If bundleGroupIds is null, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. * <pre> * Required Permissions: Either: @@ -388,14 +391,15 @@ public interface BundleManagerRemote { * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG * </pre> * @param subject user that must have proper permissions - * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group + * @param bundleGroupIds identifies the bundle groups that the new bundle will be associated with; null or zero + * length to leave unassigned. * @param distributionFileUrl a URL String to the Bundle Distribution file. It must be live, resolvable and read accessible * by the RHQ server process. * @return the persisted BundleVersion with a lot of the internal relationships filled in to help the caller * understand all that this method did. Bundle files specifically are returned. * @throws Exception */ - BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl) + BundleVersion createInitialBundleVersionViaURL(Subject subject, int[] bundleGroupIds, String distributionFileUrl) throws Exception;
/** @@ -417,9 +421,9 @@ public interface BundleManagerRemote {
/** * Like #createBundleVersionViaURL except this method will assume this is a new bundle and is responsible - * for creating the bundle as well as the bundle version. The caller can indicate which bundle group the new bundle + * for creating the bundle as well as the bundle version. The caller can indicate which bundle groups the new bundle * should be assigned to. - * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only + * If bundleGroupIds is null, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. * <pre> * Required Permissions: Either: @@ -429,7 +433,7 @@ public interface BundleManagerRemote { * </pre> * @see #createBundleVersionViaURL(org.rhq.core.domain.auth.Subject, String) */ - BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl, + BundleVersion createInitialBundleVersionViaURL(Subject subject, int[] bundleGroupIds, String distributionFileUrl, String username, String password) throws Exception;
/** diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleNotFoundException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleNotFoundException.java new file mode 100644 index 0000000..0563832 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleNotFoundException.java @@ -0,0 +1,49 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.bundle; + +import javax.ejb.ApplicationException; + +/** + * Indicates a required RHQ bundle did not exist. Note, we intentionally do not provide + * constructors that take a cause, since the three screen long Hibernate stack trace doesn't add any value here.<br/> + * Declare this an {@link ApplicationException} because we don't want these to be wrapped or to rollback an ongoing + * transaction. + */ +@ApplicationException(rollback = false, inherited = true) +public class BundleNotFoundException extends RuntimeException { + private static final long serialVersionUID = 1L; + + // Default no-arg constructor required by JAXB + public BundleNotFoundException() { + } + + /** + * Create an exception indicating the resource with the specified id was not found. + * + * @param bundleId a bundle id + */ + public BundleNotFoundException(int bundleId) { + super("A Bundle with id " + bundleId + " does not exist."); + } + + public BundleNotFoundException(String message) { + super(message); + } +} \ No newline at end of file
commit be43ef50566b878a0a1cbb7fc1bb054796ad94ac Author: Heiko W. Rupp hwr@redhat.com Date: Fri Aug 16 10:01:27 2013 +0200
BZ 966294 Add one more default when the user just accepts the default in the UI.
diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java index ea3d985..809c8a1 100644 --- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java +++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpTrapSender.java @@ -83,6 +83,7 @@ public class SnmpTrapSender implements PDUFactory { public static final int DEFAULT = 0; private static final String UDP_TRANSPORT = "udp"; private static final String TCP_TRANSPORT = "tcp"; + private static final String DEFAULT_RHQ_BINDING = "1.3.6.1.4.1.18016.2.1";
private Log log = LogFactory.getLog(SnmpTrapSender.class);
@@ -494,8 +495,8 @@ public class SnmpTrapSender implements PDUFactory { if (!this.snmpEnabled) { return "SNMP is not enabled."; } - - String variableBindingPrefix = alertParameters.getSimpleValue(SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX, null); + String variableBindingPrefix = alertParameters.getSimpleValue(SnmpInfo.PARAM_VARIABLE_BINDING_PREFIX, + DEFAULT_RHQ_BINDING);
// request id and a timestamp are added below in setSysUpTime..
commit 29ced4fcafeab720b52ba118f94e9a80284e80a2 Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 23:03:03 2013 -0400
adding status property to StorageNode
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index 54a0db5..48d5f83 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -241,6 +241,25 @@ public class StorageNode implements Serializable { this.operationMode = operationMode; }
+ public Status getStatus() { + if (operationMode == OperationMode.INSTALLED) { + return Status.INSTALLED; + } + if (operationMode == OperationMode.ANNOUNCE || operationMode == OperationMode.BOOTSTRAP || + operationMode == OperationMode.ADD_NODE_MAINTENANCE) { + if (errorMessage == null && failedOperation == null) { + return Status.JOINING; + } else { + return Status.DOWN; + } + } + if (operationMode == OperationMode.NORMAL) { + return Status.NORMAL; + } + // else operation mode is DOWN + return Status.DOWN; + } + public enum OperationMode {
DOWN("This storage node is down"), // @@ -265,6 +284,14 @@ public class StorageNode implements Serializable { } }
+ public enum Status { + INSTALLED, + DOWN, + NORMAL, + JOINING, + LEAVING + } + public String getJMXConnectionURL() { // GWT doesn't support String.format() String[] split = JMX_CONNECTION_STRING.split("%s");
commit aa86f5535c6a6fd606b56aae7258a7bb02b93ad7 Author: mtho11 mikecthompson@gmail.com Date: Thu Aug 15 12:30:49 2013 -0700
Fix for when no dashboards exist (A Dashboard doesnt exist until you go to the Dashboards screen) Metrics dashboard selection combobox bombs.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/AddToDashboardComponent.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/AddToDashboardComponent.java index f337202..8823dcf 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/AddToDashboardComponent.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/AddToDashboardComponent.java @@ -134,14 +134,16 @@ public class AddToDashboardComponent extends EnhancedToolStrip implements Enhanc }
public void onSuccess(PageList<Dashboard> dashboards) { - for (final Dashboard dashboard : dashboards) { - dashboardMenuMap.put(String.valueOf(dashboard.getId()), - MSG.view_tree_common_contextMenu_addChartToDashboard(dashboard.getName())); - dashboardMap.put(dashboard.getId(), dashboard); + if(dashboards.size() > 0){ + for (final Dashboard dashboard : dashboards) { + dashboardMenuMap.put(String.valueOf(dashboard.getId()), + MSG.view_tree_common_contextMenu_addChartToDashboard(dashboard.getName())); + dashboardMap.put(dashboard.getId(), dashboard); + } + selectedDashboard = dashboards.get(0); + dashboardSelectItem.setValueMap(dashboardMenuMap); + dashboardSelectItem.setValue(selectedDashboard.getId()); } - selectedDashboard = dashboards.get(0); - dashboardSelectItem.setValueMap(dashboardMenuMap); - dashboardSelectItem.setValue(selectedDashboard.getId()); } }); }
commit b8801597068d57eb86baadcc9e6df6f5dddec93e Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 16:31:49 2013 -0400
updating api checks
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 617593a..08e793c 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -58,6 +58,13 @@ </difference>
<difference> + <className>org/rhq/enterprise/server/cloud/StorageNodeManagerRemote</className> + <differenceType>7012</differenceType> <!-- method added to an interface --> + <method>void deployStorageNode(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.cloud.StorageNode)</method> + <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> + </difference> + + <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void assignBundlesToBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method>
commit a092d2accc9f86d5f695d4b450ec2976e469d595 Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 16:27:02 2013 -0400
[BZ 958166] Remove dependency on com.sun class
We no longer are performing the JMX calls to C* from the RHQ server but we still are making JMX calls from the Storage installer. As long as the sun.jdk module exports,
<path name="com/sun/jndi/url/rmi"/>
We do not need to have the dependency on the com.sun classes. And our build updates the sun.jdk module to export that path.
diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/pom.xml b/modules/common/cassandra-ccm/cassandra-ccm-core/pom.xml index a24ce10..ad2de77 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-core/pom.xml +++ b/modules/common/cassandra-ccm/cassandra-ccm-core/pom.xml @@ -25,18 +25,6 @@ </dependency>
<dependency> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-cassandra-jmx</artifactId> - <version>${project.version}</version> - <exclusions> - <exclusion> - <groupId>com.sun</groupId> - <artifactId>rt</artifactId> - </exclusion> - </exclusions> - </dependency> - - <dependency> <groupId>org.apache.cassandra</groupId> <artifactId>cassandra-thrift</artifactId> <version>${cassandra.version}</version> diff --git a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java index ac2313b..83851c5 100644 --- a/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java +++ b/modules/common/cassandra-ccm/cassandra-ccm-core/src/main/java/org/rhq/cassandra/ClusterInitService.java @@ -25,7 +25,6 @@
package org.rhq.cassandra;
-import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; @@ -33,27 +32,16 @@ import java.util.List; import java.util.Map; import java.util.Queue; import java.util.Set; -import java.util.UUID;
import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; -import javax.naming.Context; - -import com.datastax.driver.core.BoundStatement; -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.PreparedStatement; -import com.datastax.driver.core.ResultSet; -import com.datastax.driver.core.Row; -import com.datastax.driver.core.Session; -import com.datastax.driver.core.exceptions.NoHostAvailableException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
-import org.rhq.cassandra.installer.RMIContextFactory; import org.rhq.core.domain.cloud.StorageNode;
/** @@ -273,8 +261,6 @@ public final class ClusterInitService { String url = storageNode.getJMXConnectionURL(); JMXServiceURL serviceURL = new JMXServiceURL(url); Map<String, String> env = new HashMap<String, String>(); - // see https://issues.jboss.org/browse/AS7-2138 - env.put(Context.INITIAL_CONTEXT_FACTORY, RMIContextFactory.class.getName()); JMXConnector connector = null;
try { @@ -310,8 +296,6 @@ public final class ClusterInitService { String url = storageNode.getJMXConnectionURL(); JMXServiceURL serviceURL = new JMXServiceURL(url); Map<String, String> env = new HashMap<String, String>(); - // see https://issues.jboss.org/browse/AS7-2138 - env.put(Context.INITIAL_CONTEXT_FACTORY, RMIContextFactory.class.getName()); JMXConnector connector = null;
try { diff --git a/modules/common/cassandra-installer/pom.xml b/modules/common/cassandra-installer/pom.xml index 3a4188d..4492e70 100644 --- a/modules/common/cassandra-installer/pom.xml +++ b/modules/common/cassandra-installer/pom.xml @@ -95,11 +95,6 @@ <version>${project.version}</version> </artifactItem> <artifactItem> - <groupId>${project.groupId}</groupId> - <artifactId>rhq-cassandra-jmx</artifactId> - <version>${project.version}</version> - </artifactItem> - <artifactItem> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>${cassandra.snakeyaml.version}</version> diff --git a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java index 113d66b..3686b6f 100644 --- a/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java +++ b/modules/common/cassandra-installer/src/main/java/org/rhq/storage/installer/StorageInstaller.java @@ -46,7 +46,6 @@ import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; -import javax.naming.Context;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -66,7 +65,6 @@ import org.yaml.snakeyaml.Yaml; import org.rhq.cassandra.Deployer; import org.rhq.cassandra.DeploymentOptions; import org.rhq.cassandra.DeploymentOptionsFactory; -import org.rhq.cassandra.installer.RMIContextFactory; import org.rhq.core.util.PropertiesFileUpdate; import org.rhq.core.util.StringUtil; import org.rhq.core.util.exception.ThrowableUtil; @@ -651,8 +649,6 @@ public class StorageInstaller { }
Map<String, String> env = new HashMap<String, String>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, RMIContextFactory.class.getName()); - for (int i = 0; i < retries; ++i) { try { connector = JMXConnectorFactory.connect(serviceURL, env); diff --git a/modules/common/cassandra-installer/src/main/resources/module/main/module.xml b/modules/common/cassandra-installer/src/main/resources/module/main/module.xml index 049d30d..bf66025 100644 --- a/modules/common/cassandra-installer/src/main/resources/module/main/module.xml +++ b/modules/common/cassandra-installer/src/main/resources/module/main/module.xml @@ -7,7 +7,6 @@ <resource-root path="${project.build.finalName}.jar"/> <resource-root path="rhq-cassandra-ccm-core-${project.version}.jar"/> <resource-root path="rhq-core-util-${project.version}.jar"/> - <resource-root path="rhq-cassandra-jmx-${project.version}.jar"/> <resource-root path="snakeyaml-${cassandra.snakeyaml.version}.jar"/> </resources>
diff --git a/modules/common/cassandra-jmx/pom.xml b/modules/common/cassandra-jmx/pom.xml deleted file mode 100644 index 1653f8c..0000000 --- a/modules/common/cassandra-jmx/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ -<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/maven-v4_0_0.xsd%22%3E - - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.rhq</groupId> - <artifactId>rhq-common-parent</artifactId> - <version>4.9.0-SNAPSHOT</version> - </parent> - - <artifactId>rhq-cassandra-jmx</artifactId> - <name>RHQ Cassandra JMX Utility</name> - - <properties> - <moduleName>org.rhq.${project.artifactId}</moduleName> - </properties> - - <dependencies> - <dependency> - <groupId>com.sun</groupId> - <artifactId>rt</artifactId> - <version>1.6.0</version> - <scope>system</scope> - <systemPath>${java.home}/lib/rt.jar</systemPath> - </dependency> - </dependencies> -</project> diff --git a/modules/common/cassandra-jmx/src/main/java/org/rhq/cassandra/installer/RMIContextFactory.java b/modules/common/cassandra-jmx/src/main/java/org/rhq/cassandra/installer/RMIContextFactory.java deleted file mode 100644 index 34c456d..0000000 --- a/modules/common/cassandra-jmx/src/main/java/org/rhq/cassandra/installer/RMIContextFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * * RHQ Management Platform - * * Copyright (C) 2005-2012 Red Hat, Inc. - * * All rights reserved. - * * - * * This program is free software; you can redistribute it and/or modify - * * it under the terms of the GNU General Public License, 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.cassandra.installer; - -import java.util.Hashtable; - -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.spi.InitialContextFactory; - -import com.sun.jndi.url.rmi.rmiURLContext; - -/** - * This class is provided as part of a work around for <a href="https://issues.jboss.org/browse/AS7-2138">AS7-2138</a>. - * - * @author John Sanda - */ -public class RMIContextFactory implements InitialContextFactory { - - /* (non-Javadoc) - * @see javax.naming.spi.InitialContextFactory#getInitialContext(java.util.Hashtable) - */ - @Override - public Context getInitialContext(Hashtable environment) throws NamingException { - return new rmiURLContext(environment); - } - -} diff --git a/modules/common/pom.xml b/modules/common/pom.xml index 7d12500..45ba5c6 100644 --- a/modules/common/pom.xml +++ b/modules/common/pom.xml @@ -32,7 +32,6 @@ <module>jboss-as-dmr-client</module> <module>cassandra-auth</module> <module>cassandra-util</module> - <module>cassandra-jmx</module> <module>cassandra-schema</module> <module>cassandra-ccm</module> <module>cassandra-installer</module>
commit 89f94f89a662916eee2a2046a2d21d8d1040f2dd Author: Heiko W. Rupp hwr@redhat.com Date: Thu Aug 15 21:27:58 2013 +0200
More dbsetup/upgrade fixes related to PropertyOptionSources.
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml index 1328915..b484d2b 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml @@ -65,7 +65,7 @@ <column name="LINK_TO_TARGET" type="BOOLEAN" required="false"/> <column name="FILTER" type="VARCHAR2" required="false" size="40"/> <column name="EXPRESSION" type="VARCHAR2" required="true" size="400"/> - <column name="EXPRESSION_SCOPE" type="VARCHAR2" required="true" size="12" default="unlimited"/> + <column name="EXPRESSION_SCOPE" type="VARCHAR2" required="true" size="15" default="UNLIMITED"/> <column name="TARGET_TYPE" type="VARCHAR2" required="true" size="20"/> <column name="PROPERTY_DEF_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_DEF"/> </table> diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index ddc5de9..949ca4b 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2180,15 +2180,15 @@ </schemaSpec>
<schemaSpec version="2.136"> - <schema-addColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" columnType="VARCHAR2" precision="12"/> + <schema-addColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" columnType="VARCHAR2" precision="15"/> <schema-directSQL> <statement desc="Fill in defaults"> UPDATE RHQ_CONFIG_PD_OSRC - SET EXPRESSION_SCOPE = 'unlimited' + SET EXPRESSION_SCOPE = 'UNLIMITED' WHERE EXPRESSION_SCOPE IS NULL </statement> </schema-directSQL> - <schema-alterColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" nullable="false" default="unlimited"/> + <schema-alterColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" nullable="false" default="UNLIMITED"/> </schemaSpec>
<schemaSpec version="2.137">
commit dbe18eaa3a663b6567ce2f3b2dde7a78c4ad8565 Author: Elias Ross elias_ross@apple.com Date: Thu Jun 13 16:15:09 2013 -0700
BZ 991153 - Agent uses incorrect synchronization for 'UUID to ResourceContainer map'
When copying a 'synchronized' map, you must lock it to copy it. But this was not done. It makes sense, instead, to use a ConcurrentHashMap, especially because the copy was only done for iteration purposes.
Also, use a copy on write array for listeners
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index 7319c97..847a269 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -36,6 +36,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.Future; @@ -196,13 +197,12 @@ public class InventoryManager extends AgentService implements ContainerService, /** * UUID to ResourceContainer map */ - private Map<String, ResourceContainer> resourceContainers = Collections - .synchronizedMap(new HashMap<String, ResourceContainer>(1000)); + private final Map<String, ResourceContainer> resourceContainers = new ConcurrentHashMap<String, ResourceContainer>(100);
/** * Collection of event listeners to inform of changes to the inventory. */ - private Set<InventoryEventListener> inventoryEventListeners = new HashSet<InventoryEventListener>(); + private final Set<InventoryEventListener> inventoryEventListeners = new CopyOnWriteArraySet<InventoryEventListener>();
private PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
@@ -466,9 +466,7 @@ public class InventoryManager extends AgentService implements ContainerService, @Nullable public ResourceContainer getResourceContainer(CanonicalResourceKey canonicalId) { ResourceContainer resourceContainer = null; - Map<String, ResourceContainer> copy = new HashMap<String, ResourceContainer>(this.resourceContainers); // avoids concurrent mod exception, kinda - - for (Map.Entry<String, ResourceContainer> entry : copy.entrySet()) { + for (Map.Entry<String, ResourceContainer> entry : resourceContainers.entrySet()) { ResourceContainer container = entry.getValue(); Resource resource = container.getResource(); if (resource != null) { @@ -486,14 +484,15 @@ public class InventoryManager extends AgentService implements ContainerService, } } } - - copy.clear(); // help GC return resourceContainer; }
@Nullable public ResourceContainer getResourceContainer(Resource resource) { - return this.resourceContainers.get(resource.getUuid()); + String uuid = resource.getUuid(); + if (uuid == null) + return null; + return this.resourceContainers.get(uuid); }
@Nullable @@ -512,15 +511,13 @@ public class InventoryManager extends AgentService implements ContainerService, return null; }
- List<ResourceContainer> containers = new ArrayList<ResourceContainer>(this.resourceContainers.values()); // avoids concurrent mod exception ResourceContainer retContainer = null; - for (ResourceContainer container : containers) { + for (ResourceContainer container : resourceContainers.values()) { if (resourceId.equals(container.getResource().getId())) { retContainer = container; break; } } - containers.clear(); // help GC return retContainer; }
@@ -619,7 +616,7 @@ public class InventoryManager extends AgentService implements ContainerService, /** * This method implicitly calls {@link #handleReport(AvailabilityReport)} so any report generating entries * *will be sent to the server*. Callers should subsequently *NOT* send the report. - * + * * @param changedOnlyReport * @return The report, for inspection */ @@ -630,7 +627,7 @@ public class InventoryManager extends AgentService implements ContainerService, /** * This method implicitly calls {@link #handleReport(AvailabilityReport)} so any report generating entries * *will be sent to the server*. Callers should subsequently *NOT* send the report. - * + * * @param changedOnlyReport * @param forceChecks * @return The report, for inspection @@ -1193,7 +1190,7 @@ public class InventoryManager extends AgentService implements ContainerService, // If we synced any Resources, one or more Resource components were probably started, request a // full avail report to make sure their availabilities are determined on the next avail run (typically // < 30s away). A full avail report will ensure an initial avail check is performed for a resource. - // + // // Also kick off a service scan to scan those Resources for new child Resources. Kick both tasks off // asynchronously. // @@ -2445,9 +2442,7 @@ public class InventoryManager extends AgentService implements ContainerService, * @param listener instance to notify of change events */ public void addInventoryEventListener(InventoryEventListener listener) { - synchronized (this.inventoryEventListeners) { - this.inventoryEventListeners.add(listener); - } + this.inventoryEventListeners.add(listener); }
/** @@ -2456,9 +2451,7 @@ public class InventoryManager extends AgentService implements ContainerService, * @param listener instance to remove from event notification */ public void removeInventoryEventListener(InventoryEventListener listener) { - synchronized (this.inventoryEventListeners) { - this.inventoryEventListeners.remove(listener); - } + this.inventoryEventListeners.remove(listener); }
/** @@ -2485,9 +2478,7 @@ public class InventoryManager extends AgentService implements ContainerService, * @return all inventory event listeners */ private Set<InventoryEventListener> getInventoryEventListeners() { - synchronized (this.inventoryEventListeners) { - return new HashSet<InventoryEventListener>(this.inventoryEventListeners); - } + return this.inventoryEventListeners; }
/** @@ -2970,7 +2961,7 @@ public class InventoryManager extends AgentService implements ContainerService, }
///// - // Now we need to loop over batches of the resource ID list - asking the server for their resource representations. + // Now we need to loop over batches of the resource ID list - asking the server for their resource representations. // When we get the resources from the server, we put them in our resourceMap, keyed on ID.
Map<Integer, Resource> resourceMap = new HashMap<Integer, Resource>(resourceIdList.size()); @@ -3021,7 +3012,7 @@ public class InventoryManager extends AgentService implements ContainerService, for (Resource r : resourceBatch) { // protect against childResources notNull assumptions downstream if (null == r.getChildResources()) { - r.setChildResources(null); // this will actually initialize to an empty Set + r.setChildResources(null); // this will actually initialize to an empty Set } resourceMap.put(r.getId(), r); }
commit d35e3c466fc573748ec5dea032a417a0d304eb4f Author: Jirka Kremser jkremser@redhat.com Date: Thu Aug 15 17:34:01 2013 +0200
First version of displaying the failures of maitenance tasks on storage nodes (or the whole storage node cluster).
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java index e085eb1..a89bb81 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java @@ -23,6 +23,8 @@ import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDat import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_CQL_PORT; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_CTIME; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_DISK; +import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_ERROR_MESSAGE; +import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_FAILED_OPERATION; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_ID; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_JMX_PORT; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_MEMORY; @@ -41,6 +43,7 @@ import com.smartgwt.client.data.DataSourceField; import com.smartgwt.client.data.Record; import com.smartgwt.client.data.fields.DataSourceIntegerField; import com.smartgwt.client.data.fields.DataSourceTextField; +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; @@ -51,13 +54,16 @@ import org.rhq.core.domain.cloud.StorageNodeLoadComposite; import org.rhq.core.domain.cloud.StorageNodeLoadComposite.MeasurementAggregateWithUnits; import org.rhq.core.domain.criteria.StorageNodeCriteria; import org.rhq.core.domain.measurement.MeasurementAggregate; +import org.rhq.core.domain.operation.ResourceOperationHistory; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.PageOrdering; import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.StorageNodeLoadCompositeDatasourceField; import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter; 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.Log; import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient; import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; @@ -137,8 +143,29 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit // ListGridField cqlField = FIELD_CQL_PORT.getListGridField("90"); // cqlField.setHidden(true); // fields.add(cqlField); - fields.add(FIELD_OPERATION_MODE.getListGridField("90")); - + + field = FIELD_OPERATION_MODE.getListGridField("90"); + field.setCellFormatter(new CellFormatter() { + public String format(Object value, ListGridRecord listGridRecord, int i, int i1) { + if (listGridRecord.getAttribute(FIELD_ERROR_MESSAGE.propertyName()) != null + || listGridRecord.getAttribute(FIELD_FAILED_OPERATION.propertyName()) != null) { + return "<span style='" + DONT_MISS_ME_COLOR + "'>" + value.toString() + "</span>"; + } else + return value.toString(); + } + }); + field.setShowHover(true); + field.setHoverCustomizer(new HoverCustomizer() { + public String hoverHTML(Object value, ListGridRecord record, int rowNum, int colNum) { + if (record.getAttribute(FIELD_ERROR_MESSAGE.propertyName()) != null + || record.getAttribute(FIELD_FAILED_OPERATION.propertyName()) != null) { + return value.toString() + ": Something went wrong. Please double click on the storage node to show the detail page to know more."; + } else + return value.toString(); + } + }); + fields.add(field); + ListGridField createdTimeField = FIELD_CTIME.getListGridField("120"); TimestampCellFormatter.prepareDateField(createdTimeField); fields.add(createdTimeField); @@ -208,6 +235,13 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit record.setAttribute(FIELD_JMX_PORT.propertyName(), node.getJmxPort()); record.setAttribute(FIELD_CQL_PORT.propertyName(), node.getCqlPort()); record.setAttribute(FIELD_OPERATION_MODE.propertyName(), node.getOperationMode()); + record.setAttribute(FIELD_ERROR_MESSAGE.propertyName(), node.getErrorMessage()); + if (node.getFailedOperation() != null && node.getFailedOperation().getResource() != null) { + ResourceOperationHistory operationHistory = node.getFailedOperation(); + String value = LinkManager.getSubsystemResourceOperationHistoryLink(operationHistory.getResource().getId(), operationHistory.getId()); +// String value = "#Resource/" + operationHistory.getResource().getId() + "/Operations/History/" + operationHistory.getId()); + record.setAttribute(FIELD_FAILED_OPERATION.propertyName(), value); + } record.setAttribute(FIELD_CTIME.propertyName(), node.getCtime()); record.setAttribute(FIELD_MTIME.propertyName(), node.getMtime()); if (node.getResource() != null) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java index 19ba5ee..04a1767 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasourceField.java @@ -43,6 +43,10 @@ public enum StorageNodeDatasourceField { FIELD_MEMORY("memory", "Memory"),
FIELD_DISK("disk", "Disk"), + + FIELD_ERROR_MESSAGE("errorMessage", "Error"), + + FIELD_FAILED_OPERATION("failedOperation", "Failed Operation"),
FIELD_CTIME("ctime", CoreGUI.getMessages().view_adminTopology_serverDetail_installationDate()),
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java index dc500f0..6fdae0c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java @@ -23,6 +23,7 @@ import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDat import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_ALERTS; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_CQL_PORT; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_CTIME; +import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_FAILED_OPERATION; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_JMX_PORT; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_MTIME; import static org.rhq.enterprise.gui.coregui.client.admin.storage.StorageNodeDatasourceField.FIELD_OPERATION_MODE; @@ -49,6 +50,7 @@ import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeConfigurationComposite; import org.rhq.core.domain.criteria.StorageNodeCriteria; import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite; +import org.rhq.core.domain.operation.ResourceOperationHistory; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageList; @@ -299,16 +301,26 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, unackAlerts)); }
- StaticTextItem memoryStatusItem = new StaticTextItem("memoryStatus", "Memory"); - memoryStatusItem.setValue("No action needed"); + StaticTextItem message = new StaticTextItem("message", "Note"); + message.setValue(storageNode.getErrorMessage() == null ? "Everything is ok" : storageNode.getErrorMessage()); + + StaticTextItem lastOperation = null; + boolean isOperationFailed = storageNode.getFailedOperation() != null && storageNode.getFailedOperation().getResource() != null; + if (isOperationFailed) { + ResourceOperationHistory operationHistory = storageNode.getFailedOperation(); + String value = LinkManager.getSubsystemResourceOperationHistoryLink(operationHistory.getResource().getId(), operationHistory.getId()); +// String value = "#Resource/" + operationHistory.getResource().getId() + "/Operations/History/" + operationHistory.getId()); + lastOperation = new StaticTextItem("lastOp", "Operation"); + lastOperation.setValue(LinkManager.getHref(value, operationHistory.getOperationDefinition().getDisplayName())); + } +
- StaticTextItem diskStatusItem = new StaticTextItem("mdiskStatus", "Disk"); - diskStatusItem.setValue("No action needed");
List<FormItem> formItems = new ArrayList<FormItem>(6); formItems.addAll(Arrays.asList(nameItem, resourceItem,cqlPortItem, jmxPortItem/*, jmxConnectionUrlItem*/)); if (!CoreGUI.isDebugMode()) formItems.add(operationModeItem); // debug mode fails if this item is added - formItems.addAll(Arrays.asList(installationDateItem, lastUpdateItem, alertsItem, memoryStatusItem, diskStatusItem)); + formItems.addAll(Arrays.asList(installationDateItem, lastUpdateItem, alertsItem, message)); + if (isOperationFailed) formItems.add(lastOperation); form.setItems(formItems.toArray(new FormItem[]{}));
detailsLayout = new EnhancedVLayout();
commit 987d4fdc63ae98a0085879860cc0e2744702c696 Author: Lukas Krejci lkrejci@redhat.com Date: Thu Aug 15 13:09:14 2013 +0200
Clean up after the test.
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java index 46f2bef..1d6b49a 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java @@ -4,6 +4,8 @@ import static java.util.Arrays.asList;
import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set;
@@ -18,6 +20,7 @@ import org.rhq.core.domain.alert.AlertDampening; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.alert.AlertPriority; import org.rhq.core.domain.alert.BooleanExpression; +import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.bundle.Bundle; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.ResourceTypeBundleConfiguration; @@ -54,6 +57,9 @@ import org.rhq.enterprise.server.util.LookupUtil; public class ResourceMetadataManagerBeanTest extends MetadataBeanTest {
private static final String PLUGIN_NAME = "ResourceMetadataManagerBeanTestPlugin"; + //this is used in afterclass, which might execute with a different instance than the rest of the tests + //therefore we need to make this static. Not sure who causes this, if it is Arq or TestNG itself. + private static Set<Integer> groupIds = Collections.synchronizedSet(new HashSet<Integer>());
@Test(groups = { "plugin.resource.metadata.test", "NewPlugin" }) public void testRemovalOfObsoleteBundleAndDriftConfig() throws Exception { @@ -607,9 +613,16 @@ public class ResourceMetadataManagerBeanTest extends MetadataBeanTest { }
// this needs to be the last test executed in the class, it does cleanup - @Test(priority = 10, alwaysRun = true, dependsOnGroups = { "RemoveTypes" }) + @Test(priority = 1000, alwaysRun = true, dependsOnGroups = { "RemoveTypes" }) public void afterClassWorkTest() throws Exception { afterClassWork(); + + Subject overlord = LookupUtil.getSubjectManager().getOverlord(); + ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager(); + + for(int id : groupIds) { + groupManager.deleteResourceGroup(overlord, id); + } }
void assertTypesPersisted(String msg, List<String> types, String plugin) { @@ -714,6 +727,7 @@ public class ResourceMetadataManagerBeanTest extends MetadataBeanTest { ResourceGroup resourceGroup = new ResourceGroup(groupName, resourceType); resourceGroup.setRecursive(recursive); ResourceGroup result = resourceGroupMgr.createResourceGroup(subjectMgr.getOverlord(), resourceGroup); + groupIds.add(result.getId()); return result; }
commit f78f1dca5dfb8d4983a8fe614f55be9c9b6a745f Author: Lukas Krejci lkrejci@redhat.com Date: Thu Aug 15 13:08:45 2013 +0200
[BZ 988881] - GUI now refreshes availability every 15s.
Getting the live availability or live value of a metric now triggers alerts.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java index 3248186..eb0e85b 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java @@ -26,6 +26,7 @@ import com.google.gwt.user.client.rpc.RemoteService;
import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.criteria.ResourceCriteria; +import org.rhq.core.domain.measurement.ResourceAvailability; import org.rhq.core.domain.resource.Agent; import org.rhq.core.domain.resource.CreateResourceHistory; import org.rhq.core.domain.resource.DeleteResourceHistory; @@ -69,6 +70,8 @@ public interface ResourceGWTService extends RemoteService {
ResourceAvailabilitySummary getResourceAvailabilitySummary(int resourceId) throws RuntimeException;
+ ResourceAvailability getLiveResourceAvailability(int resourceId) throws RuntimeException; + PageList<Resource> findResourcesByCriteria(ResourceCriteria criteria) throws RuntimeException;
List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources, int maxResourcesByType) diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceErrorsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceErrorsView.java index b214edc..b46e075 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceErrorsView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceErrorsView.java @@ -169,7 +169,7 @@ public class ResourceErrorsView extends Table<ResourceErrorsDataSource> { @Override public void refresh() { super.refresh(); - this.titleBar.refresh(); + this.titleBar.refreshResourceErrors(); }
private void popupDetails(String details) { @@ -188,7 +188,7 @@ public class ResourceErrorsView extends Table<ResourceErrorsDataSource> { winModal.addCloseClickHandler(new CloseClickHandler() { public void onCloseClick(CloseClickEvent event) { winModal.markForDestroy(); - titleBar.refresh(); + titleBar.refreshResourceErrors(); } });
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java index 85dde83..fbbf0a8 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTitleBar.java @@ -23,9 +23,12 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set;
+import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.types.Alignment; +import com.smartgwt.client.types.Cursor; import com.smartgwt.client.types.VerticalAlignment; +import com.smartgwt.client.widgets.Button; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.HTMLFlow; import com.smartgwt.client.widgets.Img; @@ -33,13 +36,13 @@ import com.smartgwt.client.widgets.Label; import com.smartgwt.client.widgets.Window; import com.smartgwt.client.widgets.events.ClickEvent; import com.smartgwt.client.widgets.events.ClickHandler; -import com.smartgwt.client.widgets.events.DoubleClickEvent; -import com.smartgwt.client.widgets.events.DoubleClickHandler; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.SpacerItem;
import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.criteria.ResourceCriteria; +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.domain.measurement.ResourceAvailability; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceError; @@ -53,6 +56,9 @@ import org.rhq.enterprise.gui.coregui.client.components.tagging.TagEditorView; import org.rhq.enterprise.gui.coregui.client.components.tagging.TagsChangedCallback; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; +import org.rhq.enterprise.gui.coregui.client.util.async.Command; +import org.rhq.enterprise.gui.coregui.client.util.async.CountDownLatch; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; @@ -74,6 +80,8 @@ public class ResourceTitleBar extends EnhancedVLayout { private static final String COLLAPSED_TOOLTIP = MSG.view_portlet_inventory_tooltip_expand(); private static final String EXPANDED_TOOLTIP = MSG.view_portlet_inventory_tooltip_collapse(); private static final String PLUGIN_ERRORS_ICON = "[SKIN]/Dialog/warn.png"; + private static final String LOADING_ICON = "ajax-loader.gif"; + private Img expandCollapseArrow;
private Resource resource; @@ -87,6 +95,14 @@ public class ResourceTitleBar extends EnhancedVLayout { private EnhancedHLayout detailsForm; private OverviewForm detailsFormSummary; private Img pluginErrors; + private Img loading; + + private Timer resourceAvailAndErrorsRefreshTime = new Timer() { + @Override + public void run() { + refreshAvailAndResourceErrors(); + } + };
public ResourceTitleBar() { super(); @@ -116,14 +132,9 @@ public class ResourceTitleBar extends EnhancedVLayout { this.title.setWidth("*");
this.availabilityImage = new Img(ImageManager.getAvailabilityLargeIcon(null), 24, 24); - this.availabilityImage.addDoubleClickHandler(new DoubleClickHandler() { - public void onDoubleClick(DoubleClickEvent event) { - refresh(); - } - });
this.favoriteButton = new Img(NOT_FAV_ICON, 24, 24); - + this.favoriteButton.setCursor(Cursor.POINTER); this.favoriteButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent clickEvent) { Set<Integer> favorites = toggleFavoriteLocally(); @@ -179,7 +190,6 @@ public class ResourceTitleBar extends EnhancedVLayout {
pluginErrors = new Img(PLUGIN_ERRORS_ICON, 24, 24); pluginErrors.setVisible(false); - refreshPluginErrors(); // this is an async call
//define tool tip pluginErrors.setPrompt(MSG.view_resource_title_component_errors_tooltip()); @@ -227,10 +237,15 @@ public class ResourceTitleBar extends EnhancedVLayout { } });
+ loading = new Img(LOADING_ICON, 16, 16); + loading.setVisible(false); + loading.setValign(VerticalAlignment.CENTER); + //top information top.addMember(expandCollapseArrow); top.addMember(badge); top.addMember(title); + top.addMember(loading); top.addMember(pluginErrors); top.addMember(availabilityImage); top.addMember(favoriteButton); @@ -267,6 +282,17 @@ public class ResourceTitleBar extends EnhancedVLayout { } addMember(details); ResourceTitleBar.this.markForRedraw(); + + resourceAvailAndErrorsRefreshTime.scheduleRepeating(15000); + } + + @Override + protected void onUnload() { + if (resourceAvailAndErrorsRefreshTime != null) { + resourceAvailAndErrorsRefreshTime.cancel(); + } + + super.onUnload(); }
private void loadTags(final TagEditorView tagEditorView) { @@ -344,11 +370,27 @@ public class ResourceTitleBar extends EnhancedVLayout { return favorites; }
- public void refresh() { - refreshPluginErrors(); + public void refreshResourceErrors() { + refreshErrors(null); + } + + public void refreshAvailAndResourceErrors() { + CountDownLatch latch = CountDownLatch.create(2, new Command() { + @Override + public void execute() { + loading.setVisible(false); + markForRedraw(); + } + }); + + loading.setVisible(true); + loading.markForRedraw(); + + refreshAvailability(latch); + refreshErrors(latch); }
- private void refreshPluginErrors() { + private void refreshErrors(final CountDownLatch latch) { GWTServiceLookup.getResourceService().findResourceErrors(resourceComposite.getResource().getId(), new AsyncCallback<List<ResourceError>>() { public void onFailure(Throwable caught) { @@ -356,15 +398,59 @@ public class ResourceTitleBar extends EnhancedVLayout { CoreGUI.getErrorHandler().handleError( MSG.dataSource_resourceErrors_error_fetchFailure(String.valueOf(resourceComposite.getResource() .getId())), caught); + + if (latch != null) { + latch.countDown(); + } else { + markForRedraw(); + } }
public void onSuccess(List<ResourceError> result) { pluginErrors.setVisible(!result.isEmpty()); - markForRedraw(); + + if (latch != null) { + latch.countDown(); + } else { + markForRedraw(); + } } }); }
+ private void refreshAvailability(final CountDownLatch latch) { + final AvailabilityType currentAvail = resource.getCurrentAvailability().getAvailabilityType(); + + GWTServiceLookup.getResourceService().getLiveResourceAvailability(resource.getId(), + new AsyncCallback<ResourceAvailability>() { + + @Override + public void onFailure(Throwable caught) { + availabilityImage.setSrc(ImageManager.getAvailabilityLargeIconFromAvailType(currentAvail)); + CoreGUI.getErrorHandler().handleError("I18N: Failed to refresh the availability", caught); + //MSG.dataSource_resourceErrors_error_fetchFailure(String.valueOf(resourceComposite.getResource() + // .getId())), caught); + if (latch != null) { + latch.countDown(); + } else { + markForRedraw(); + } + } + + @Override + public void onSuccess(ResourceAvailability result) { + availabilityImage.setSrc(ImageManager.getAvailabilityLargeIconFromAvailType(result.getAvailabilityType())); + resource.setCurrentAvailability(result); + availabilityImage.markForRedraw(); + if (latch != null) { + latch.countDown(); + } else { + markForRedraw(); + } + } + }); + } + public class UpdateFavoritesCallback implements AsyncCallback<Subject> { public void onSuccess(Subject subject) { String msg = null; @@ -391,4 +477,4 @@ public class ResourceTitleBar extends EnhancedVLayout { } }
-} \ No newline at end of file +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java index dfa1b9f..fbf5d7b 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java @@ -33,6 +33,7 @@ import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.configuration.definition.ConfigurationTemplate; import org.rhq.core.domain.criteria.ResourceCriteria; +import org.rhq.core.domain.measurement.ResourceAvailability; import org.rhq.core.domain.resource.Agent; import org.rhq.core.domain.resource.CannotConnectToAgentException; import org.rhq.core.domain.resource.CreateResourceHistory; @@ -135,6 +136,15 @@ public class ResourceGWTServiceImpl extends AbstractGWTServiceImpl implements Re } }
+ @Override + public ResourceAvailability getLiveResourceAvailability(int resourceId) throws RuntimeException { + try { + return SerialUtility.prepare(resourceManager.getLiveResourceAvailability(getSessionSubject(), resourceId), "ResourceService.getLiveResourceAvailability"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + public PageList<Resource> findResourcesByCriteria(ResourceCriteria criteria) throws RuntimeException { try { PageList<Resource> result = resourceManager.findResourcesByCriteria(getSessionSubject(), criteria); diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java index 3797542..153cc3d 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/alert/test/AlertConditionTest.java @@ -23,8 +23,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set;
-import javax.persistence.NoResultException; - import org.testng.Assert; import org.testng.annotations.Test;
@@ -38,7 +36,6 @@ import org.rhq.core.domain.alert.AlertDampening.Category; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.alert.AlertPriority; import org.rhq.core.domain.alert.BooleanExpression; -import org.rhq.core.domain.cloud.Server; import org.rhq.core.domain.criteria.AlertCriteria; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.discovery.AvailabilityReport; @@ -49,7 +46,6 @@ import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.measurement.MeasurementReport; import org.rhq.core.domain.measurement.MeasurementSchedule; import org.rhq.core.domain.measurement.MeasurementScheduleRequest; -import org.rhq.core.domain.resource.Agent; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.util.PageControl; @@ -69,12 +65,7 @@ import org.rhq.enterprise.server.util.LookupUtil; public class AlertConditionTest extends UpdatePluginMetadataTestBase { private static final boolean ENABLED = true;
- // this must match the constant found in ServerManagerBean - private static final String RHQ_SERVER_NAME_PROPERTY = "rhq.server.high-availability.name"; - private static final String RHQ_SERVER_NAME_PROPERTY_VALUE = "AlertConditionTestServer"; - private Resource resource; - private Server server;
@Override protected String getSubsystemDirectory() { @@ -82,22 +73,12 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase { }
@Override - protected void beforeMethod() throws Exception { - super.beforeMethod(); - System.setProperty(RHQ_SERVER_NAME_PROPERTY, RHQ_SERVER_NAME_PROPERTY_VALUE); - } - - @Override protected void afterMethod() throws Exception { if (resource != null) { deleteNewResource(resource); resource = null; }
- deleteServerIdentity(); - - System.setProperty(RHQ_SERVER_NAME_PROPERTY, ""); - super.afterMethod(); }
@@ -661,32 +642,4 @@ public class AlertConditionTest extends UpdatePluginMetadataTestBase { LookupUtil.getAlertConditionCacheManager().reloadAllCaches(); }
- private void createServerIdentity() { - server = new Server(); - server.setName(RHQ_SERVER_NAME_PROPERTY_VALUE); - server.setAddress("localhost"); - server.setPort(7080); - server.setSecurePort(7443); - server.setComputePower(1); - server.setOperationMode(Server.OperationMode.MAINTENANCE); - int serverId = LookupUtil.getServerManager().create(server); - assert serverId > 0 : "could not create our server identity in the DB"; - - // simulate the agent being "connected" to the server - try { - Agent agent = getAgent(); - agent.setServer(server); - LookupUtil.getAgentManager().updateAgent(agent); - } catch (NoResultException nre) { - // no agent to attach - } - } - - private void deleteServerIdentity() throws Exception { - if (server != null) { - cleanupAgent(); // can't remove the server before we purge the agent - LookupUtil.getTopologyManager().deleteServer(LookupUtil.getSubjectManager().getOverlord(), server.getId()); - server = null; - } - } } diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java index 9f49143..dbd03ae 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBeanTest.java @@ -34,8 +34,11 @@ import static org.rhq.test.AssertUtils.assertPropertiesMatch; import java.math.BigDecimal; import java.math.MathContext; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set;
import javax.ejb.EJB;
@@ -43,12 +46,30 @@ import com.datastax.driver.core.exceptions.NoHostAvailableException;
import org.joda.time.DateTime; import org.joda.time.Hours; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.testng.annotations.Test;
+import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService; +import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService; +import org.rhq.core.domain.alert.Alert; +import org.rhq.core.domain.alert.AlertCondition; +import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertConditionOperator; +import org.rhq.core.domain.alert.AlertDampening; +import org.rhq.core.domain.alert.AlertDefinition; +import org.rhq.core.domain.alert.AlertPriority; +import org.rhq.core.domain.alert.BooleanExpression; import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.cloud.Server; import org.rhq.core.domain.common.EntityContext; +import org.rhq.core.domain.criteria.AlertCriteria; import org.rhq.core.domain.criteria.ResourceCriteria; +import org.rhq.core.domain.measurement.Availability; +import org.rhq.core.domain.measurement.AvailabilityType; import org.rhq.core.domain.measurement.MeasurementAggregate; +import org.rhq.core.domain.measurement.MeasurementData; import org.rhq.core.domain.measurement.MeasurementDataNumeric; import org.rhq.core.domain.measurement.MeasurementDefinition; import org.rhq.core.domain.measurement.MeasurementReport; @@ -56,14 +77,18 @@ import org.rhq.core.domain.measurement.MeasurementSchedule; import org.rhq.core.domain.measurement.MeasurementScheduleRequest; import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite; 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.ResourceType; +import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.drift.DriftServerPluginService; import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.storage.StorageClientManagerBean; import org.rhq.enterprise.server.test.AbstractEJB3Test; +import org.rhq.enterprise.server.test.TestServerCommunicationsService; import org.rhq.enterprise.server.test.TransactionCallback; +import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.enterprise.server.util.ResourceTreeHelper; import org.rhq.server.metrics.MetricsDAO; import org.rhq.server.metrics.StorageSession; @@ -77,6 +102,10 @@ import org.rhq.test.AssertUtils; */ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
+ // this must match the constant found in ServerManagerBean + private static final String RHQ_SERVER_NAME_PROPERTY = "rhq.server.high-availability.name"; + private static final String RHQ_SERVER_NAME_PROPERTY_VALUE = "TestServer"; + //private final Log log = LogFactory.getLog(MeasurementDataManagerBeanTest.class);
private static final boolean ENABLED = true; @@ -101,6 +130,8 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
private ResourceType resourceType;
+ private Server server; + private Agent agent;
private MeasurementDefinition dynamicMeasuremenDef; @@ -109,7 +140,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
private MeasurementSchedule dynamicSchedule;
- private Subject overlord; + private AlertDefinition alertDefinition;
@EJB private SubjectManagerLocal subjectManager; @@ -125,9 +156,17 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
private MetricsDAO metricsDAO;
+ private TestServerCommunicationsService agentServiceContainer; + + private Subject getOverlord() { + return subjectManager.getOverlord(); + } + @Override protected void beforeMethod() throws Exception { - overlord = subjectManager.getOverlord(); + agentServiceContainer = prepareForTestAgents(); + + prepareScheduler();
metricsDAO = storageClientManager.getMetricsDAO();
@@ -137,15 +176,21 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { prepareCustomServerPluginService(driftServerPluginService); driftServerPluginService.masterConfig.getPluginDirectory().mkdirs();
+ System.setProperty(RHQ_SERVER_NAME_PROPERTY, RHQ_SERVER_NAME_PROPERTY_VALUE); + createInventory(); insertDummyReport(); + + agentServiceContainer.addStartedAgent(agent); }
@Override protected void afterMethod() throws Exception { - purgeDB(); + purgeDB(true);
unprepareServerPluginService(); + unprepareScheduler(); + unprepareForTestAgents(); }
@Test(enabled = ENABLED) @@ -168,7 +213,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { dataManager.mergeMeasurementReport(report); waitForRawInserts();
- List<MeasurementDataNumericHighLowComposite> actualData = findDataForContext(overlord, + List<MeasurementDataNumericHighLowComposite> actualData = findDataForContext(getOverlord(), EntityContext.forResource(resource.getId()), dynamicSchedule, beginTime.getMillis(), endTime.getMillis());
assertEquals("Expected to get back 60 data points.", buckets.getNumDataPoints(), actualData.size()); @@ -213,7 +258,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { dataManager.mergeMeasurementReport(report); waitForRawInserts();
- MeasurementAggregate actual = dataManager.getAggregate(overlord, dynamicSchedule.getId(), + MeasurementAggregate actual = dataManager.getAggregate(getOverlord(), dynamicSchedule.getId(), beginTime.getMillis(), endTime.getMillis());
MeasurementAggregate expected = new MeasurementAggregate(1.1, divide((1.1 + 2.2 + 3.3 + 4.4 + 5.5 + 6.6), 6), @@ -244,7 +289,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
insert1HourData(data);
- List<MeasurementDataNumericHighLowComposite> actualData = findDataForContext(overlord, + List<MeasurementDataNumericHighLowComposite> actualData = findDataForContext(getOverlord(), EntityContext.forResource(resource.getId()), dynamicSchedule, beginTime.getMillis(), endTime.getMillis());
assertEquals("Expected to get back 60 data points.", buckets.getNumDataPoints(), actualData.size()); @@ -260,8 +305,50 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { actualData.get(59), 0.0001D); }
+ @Test(enabled = ENABLED) + public void gettingLiveDataTriggersAlerts() throws Exception { + agentServiceContainer.measurementService = Mockito.mock(MeasurementAgentService.class); + + Mockito.when(agentServiceContainer.measurementService.getRealTimeMeasurementValue(Mockito.anyInt(), Mockito.anySetOf(MeasurementScheduleRequest.class))).then( + new Answer<Set<MeasurementData>>() { + @Override + @SuppressWarnings("unchecked") + public Set<MeasurementData> answer(InvocationOnMock invocation) throws Throwable { + Set<MeasurementScheduleRequest> requests = (Set<MeasurementScheduleRequest>) invocation.getArguments()[1]; + + Set<MeasurementData> ret = new HashSet<MeasurementData>(); + for(MeasurementScheduleRequest req : requests) { + ret.add(new MeasurementDataNumeric(System.currentTimeMillis(), req, (double) System.nanoTime())); + } + + return ret; + } + }); + + dataManager.findLiveData(getOverlord(), resource.getId(), new int[] { dynamicMeasuremenDef.getId()}, Long.MAX_VALUE); + // wait for our JMS messages to process and see if we get any alerts + Thread.sleep(3000); + + //need to do this so that we don't have to wait on server's heartbeat to propagate the + //collected value into the alert condition cache + LookupUtil.getAlertConditionCacheManager().reloadAllCaches(); + + //this first metric collection doesn't trigger alerts because there's no "history" to compare against + //let's trigger another metric collection so that we see the alert fire... + dataManager.findLiveData(getOverlord(), resource.getId(), new int[] { dynamicMeasuremenDef.getId()}, Long.MAX_VALUE); + // wait for our JMS messages to process and see if we get any alerts + Thread.sleep(3000); + + //check that the alert fired when the value of the measurement changed. + AlertCriteria aCrit = new AlertCriteria(); + aCrit.addFilterResourceIds(resource.getId()); + + List<Alert> alerts = LookupUtil.getAlertManager().findAlertsByCriteria(getOverlord(), aCrit); + assertEquals("Unexpected number of alerts on the resource.", 1, alerts.size()); + } + private void createInventory() throws Exception { - purgeDB(); + purgeDB(false); executeInTransaction(false, new TransactionCallback() { @Override public void execute() throws Exception { @@ -269,7 +356,18 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { resourceType = new ResourceType(RESOURCE_TYPE, PLUGIN, SERVER, null); em.persist(resourceType);
+ server = new Server(); + server.setName(RHQ_SERVER_NAME_PROPERTY_VALUE); + server.setAddress("localhost"); + server.setPort(7080); + server.setSecurePort(7443); + server.setComputePower(1); + server.setOperationMode(Server.OperationMode.MAINTENANCE); + int serverId = LookupUtil.getServerManager().create(server); + assert serverId > 0 : "could not create our server identity in the DB"; + agent = new Agent(AGENT_NAME, "localhost", 9999, "", "randomToken"); + agent.setServer(server); em.persist(agent);
dynamicMeasuremenDef = new MeasurementDefinition(resourceType, DYNAMIC_DEF_NAME); @@ -281,6 +379,7 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test {
resource = new Resource(RESOURCE_KEY, RESOURCE_NAME, resourceType); resource.setUuid(RESOURCE_UUID); + resource.setInventoryStatus(InventoryStatus.COMMITTED); resource.setAgent(agent);
em.persist(resource); @@ -292,29 +391,65 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { em.persist(dynamicSchedule); } }); + + alertDefinition = new AlertDefinition(); + AlertCondition cond = new AlertCondition(alertDefinition, AlertConditionCategory.CHANGE); + cond.setName(DYNAMIC_DEF_NAME); + cond.setMeasurementDefinition(dynamicMeasuremenDef); + alertDefinition.setName("liveDataTestAlert"); + alertDefinition.setResource(resource); + alertDefinition.setPriority(AlertPriority.MEDIUM); + alertDefinition.setRecoveryId(0); + alertDefinition.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE)); + alertDefinition.setConditions(Collections.singleton(cond)); + alertDefinition.setEnabled(true); + alertDefinition.setConditionExpression(BooleanExpression.ALL); + + AlertDefinitionManagerLocal alertDefinitionManager = LookupUtil.getAlertDefinitionManager(); + //needs to be done outside of the above transaction, so that the createAlert... method can "see" the resource. + alertDefinitionManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDefinition, resource.getId(), true); + + //obvious, right? This needs to be done for the alert subsystem to become aware of the new def + LookupUtil.getAlertConditionCacheManager().reloadAllCaches(); }
- private void purgeDB() { + private void purgeDB(final boolean assumeResourceExists) { purgeMetricsTables();
+ ResourceCriteria c = new ResourceCriteria(); + c.addFilterInventoryStatus(null); + c.addFilterResourceKey(RESOURCE_KEY); + c.fetchSchedules(true); + c.fetchAlertDefinitions(true); + + final List<Resource> r = resourceManager.findResourcesByCriteria(subjectManager.getOverlord(), c); + if (assumeResourceExists && !r.isEmpty()) { + assertTrue("Should be only 1 resource", r.size() == 1); + } + + if (!r.isEmpty()) { + Resource doomedResource = r.get(0); + deleteAlertDefinitions(doomedResource.getAlertDefinitions()); + } + executeInTransaction(false, new TransactionCallback() { @Override public void execute() throws Exception { - ResourceCriteria c = new ResourceCriteria(); - c.addFilterInventoryStatus(null); - c.addFilterResourceKey(RESOURCE_KEY); - c.fetchSchedules(true); - List<Resource> r = resourceManager.findResourcesByCriteria(subjectManager.getOverlord(), c); - - // Note that the order of deletes is important due to FK - // constraints. + if (!r.isEmpty()) { - assertTrue("Should be only 1 resource", r.size() == 1); - Resource doomedResource = r.get(0); - deleteMeasurementSchedules(doomedResource); - deleteResource(doomedResource); + //load the resource entity again within this transaction so that we + //have an attached copy of it. + Resource delete = em.find(Resource.class, r.get(0).getId()); + + + // Note that the order of deletes is important due to FK + // constraints. + deleteMeasurementSchedules(delete); + deleteResource(delete); } + deleteAgent(); + deleteServer(); deleteDynamicMeasurementDef(); deleteResourceType(); } @@ -330,6 +465,10 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { em.createQuery("delete from Agent where name = :name").setParameter("name", AGENT_NAME).executeUpdate(); }
+ private void deleteServer() { + em.createQuery("delete from Server where name = :name").setParameter("name", RHQ_SERVER_NAME_PROPERTY_VALUE).executeUpdate(); + } + private void deleteResourceType() { em.createQuery("delete from ResourceType where name = :name and plugin = :plugin") .setParameter("name", RESOURCE_TYPE).setParameter("plugin", PLUGIN).executeUpdate(); @@ -349,6 +488,26 @@ public class MeasurementDataManagerBeanTest extends AbstractEJB3Test { } }
+ private void deleteAlertDefinitions(Collection<AlertDefinition> defs) { + AlertDefinitionManagerLocal alertDefinitionManager = LookupUtil.getAlertDefinitionManager(); + + int[] ids = new int[defs.size()]; + int i = 0; + for(AlertDefinition def : defs) { + ids[i++] = def.getId(); + + LookupUtil.getAlertManager() + .deleteAlertsByContext(getOverlord(), EntityContext.forResource(def.getResource().getId())); + } + + alertDefinitionManager.removeAlertDefinitions(getOverlord(), ids); + + alertDefinitionManager.purgeUnusedAlertDefinitions(); + for(i = 0; i < ids.length; ++i) { + alertDefinitionManager.purgeInternals(ids[i]); + } + } + private void insertDummyReport() { // we insert the dummy report due to https://bugzilla.redhat.com/show_bug.cgi?id=822240 DateTime now = new DateTime(); diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java index ac4ba79..abdc281 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdatePluginMetadataTestBase.java @@ -38,6 +38,7 @@ import org.rhq.core.clientapi.agent.measurement.MeasurementAgentService; import org.rhq.core.clientapi.descriptor.DescriptorPackages; import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor; import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.cloud.Server; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.criteria.ResourceTypeCriteria; import org.rhq.core.domain.measurement.MeasurementData; @@ -61,6 +62,10 @@ import org.rhq.enterprise.server.util.LookupUtil;
public class UpdatePluginMetadataTestBase extends AbstractEJB3Test {
+ // this must match the constant found in ServerManagerBean + protected static final String RHQ_SERVER_NAME_PROPERTY = "rhq.server.high-availability.name"; + protected static final String RHQ_SERVER_NAME_PROPERTY_VALUE = "TestServer"; + protected TestServerCommunicationsService agentServiceContainer;
protected static final String PLUGIN_NAME = "UpdatePluginMetadataTestBasePlugin"; // don't change this - our test descriptor .xml files use it as plugin name @@ -70,6 +75,7 @@ public class UpdatePluginMetadataTestBase extends AbstractEJB3Test { protected static PluginManagerLocal pluginMgr; protected static ResourceTypeManagerLocal resourceTypeManager; protected static ResourceManagerLocal resourceManager; + private Server server;
@Override protected void beforeMethod() throws Exception { @@ -86,6 +92,8 @@ public class UpdatePluginMetadataTestBase extends AbstractEJB3Test { pluginMgr = LookupUtil.getPluginManager(); resourceTypeManager = LookupUtil.getResourceTypeManager(); resourceManager = LookupUtil.getResourceManager(); + + System.setProperty(RHQ_SERVER_NAME_PROPERTY, RHQ_SERVER_NAME_PROPERTY_VALUE); }
@Override @@ -96,6 +104,10 @@ public class UpdatePluginMetadataTestBase extends AbstractEJB3Test { unpreparePluginScannerService(); unprepareScheduler(); unprepareForTestAgents(); + + deleteServerIdentity(); + + System.setProperty(RHQ_SERVER_NAME_PROPERTY, ""); }
protected void prepareMockAgentServiceContainer() { @@ -261,6 +273,35 @@ public class UpdatePluginMetadataTestBase extends AbstractEJB3Test { agentServiceContainer.addStartedAgent(agent); }
+ protected void createServerIdentity() { + server = new Server(); + server.setName(RHQ_SERVER_NAME_PROPERTY_VALUE); + server.setAddress("localhost"); + server.setPort(7080); + server.setSecurePort(7443); + server.setComputePower(1); + server.setOperationMode(Server.OperationMode.MAINTENANCE); + int serverId = LookupUtil.getServerManager().create(server); + assert serverId > 0 : "could not create our server identity in the DB"; + + // simulate the agent being "connected" to the server + try { + Agent agent = getAgent(); + agent.setServer(server); + LookupUtil.getAgentManager().updateAgent(agent); + } catch (NoResultException nre) { + // no agent to attach + } + } + + protected void deleteServerIdentity() throws Exception { + if (server != null) { + cleanupAgent(); // can't remove the server before we purge the agent + LookupUtil.getTopologyManager().deleteServer(LookupUtil.getSubjectManager().getOverlord(), server.getId()); + server = null; + } + } + /** * A dummy that needs to be set up before running ResourceManager.deleteResource() */ diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java index 1fbeb3c..660afed 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/test/ResourceManagerBeanTest.java @@ -18,17 +18,40 @@ */ package org.rhq.enterprise.server.resource.test;
+import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.UUID;
import javax.transaction.NotSupportedException; import javax.transaction.SystemException;
+import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.testng.annotations.Test;
+import org.jboss.remoting.InvokerLocator; + +import org.rhq.core.clientapi.agent.discovery.DiscoveryAgentService; +import org.rhq.core.domain.alert.Alert; +import org.rhq.core.domain.alert.AlertCondition; +import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertConditionOperator; +import org.rhq.core.domain.alert.AlertDampening; +import org.rhq.core.domain.alert.AlertDefinition; +import org.rhq.core.domain.alert.AlertPriority; +import org.rhq.core.domain.alert.BooleanExpression; import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.criteria.AlertCriteria; +import org.rhq.core.domain.criteria.AlertDefinitionCriteria; +import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.criteria.ResourceGroupCriteria; +import org.rhq.core.domain.measurement.Availability; +import org.rhq.core.domain.measurement.AvailabilityType; +import org.rhq.core.domain.measurement.MeasurementDefinition; +import org.rhq.core.domain.measurement.ResourceAvailability; import org.rhq.core.domain.resource.Agent; import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.Resource; @@ -39,8 +62,13 @@ import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.group.GroupCategory; import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.util.PageList; +import org.rhq.enterprise.communications.ServiceContainer; +import org.rhq.enterprise.communications.command.server.CommandProcessorMetrics; +import org.rhq.enterprise.server.agentclient.AgentClient; +import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal; import org.rhq.enterprise.server.auth.SessionManager; import org.rhq.enterprise.server.auth.SessionNotFoundException; +import org.rhq.enterprise.server.core.comm.ServerConfiguration; import org.rhq.enterprise.server.discovery.DiscoveryServerServiceImpl; import org.rhq.enterprise.server.operation.OperationDefinitionNotFoundException; import org.rhq.enterprise.server.resource.ResourceManagerLocal; @@ -51,6 +79,7 @@ import org.rhq.enterprise.server.resource.group.ResourceGroupNotFoundException; import org.rhq.enterprise.server.resource.group.definition.exception.GroupDefinitionNotFoundException; import org.rhq.enterprise.server.resource.metadata.test.UpdatePluginMetadataTestBase; import org.rhq.enterprise.server.test.TestServerCommunicationsService; +import org.rhq.enterprise.server.test.TestServerCommunicationsServiceMBean; import org.rhq.enterprise.server.util.LookupUtil;
/** @@ -58,39 +87,25 @@ import org.rhq.enterprise.server.util.LookupUtil; */ @Test public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { - private Subject overlord; private Resource newResource; private ResourceGroup newGroup; private ResourceGroupManagerLocal groupManager;
- TestServerCommunicationsService agentServiceContainer; - @Override protected void beforeMethod() throws Exception { super.beforeMethod();
- overlord = LookupUtil.getSubjectManager().getOverlord(); newResource = createNewResourceWithNewType(); groupManager = LookupUtil.getResourceGroupManager(); newGroup = createNewGroup(); }
- @Override - protected void afterMethod() throws Exception { - if (newGroup != null) { - groupManager.deleteResourceGroup(overlord, newGroup.getId()); - } - deleteNewResourceAgentResourceType(newResource); - - super.afterMethod(); - } - public void testResourceErrors() { ResourceError error; List<ResourceError> errors; DiscoveryServerServiceImpl serverService = new DiscoveryServerServiceImpl();
- errors = resourceManager.findResourceErrors(overlord, newResource.getId(), + errors = resourceManager.findResourceErrors(getOverlord(), newResource.getId(), ResourceErrorType.INVALID_PLUGIN_CONFIGURATION); assert errors.size() == 0;
@@ -100,7 +115,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { // simulate the agent notifying the server about an error // this will exercise the addResourceError in the SLSB serverService.setResourceError(error); - errors = resourceManager.findResourceErrors(overlord, newResource.getId(), + errors = resourceManager.findResourceErrors(getOverlord(), newResource.getId(), ResourceErrorType.INVALID_PLUGIN_CONFIGURATION); assert errors.size() == 1; error = errors.get(0); @@ -118,7 +133,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { error.setSummary("another summary"); error.setDetail("another detail"); serverService.setResourceError(error); - errors = resourceManager.findResourceErrors(overlord, newResource.getId(), + errors = resourceManager.findResourceErrors(getOverlord(), newResource.getId(), ResourceErrorType.INVALID_PLUGIN_CONFIGURATION); assert errors.size() == 1; error = errors.get(0); @@ -128,12 +143,22 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { assert error.getErrorType() == ResourceErrorType.INVALID_PLUGIN_CONFIGURATION; assert error.getTimeOccurred() == 567890;
- resourceManager.deleteResourceError(overlord, error.getId()); - errors = resourceManager.findResourceErrors(overlord, newResource.getId(), + resourceManager.deleteResourceError(getOverlord(), error.getId()); + errors = resourceManager.findResourceErrors(getOverlord(), newResource.getId(), ResourceErrorType.INVALID_PLUGIN_CONFIGURATION); assert errors.size() == 0; }
+ @Override + protected void afterMethod() throws Exception { + if (newGroup != null) { + groupManager.deleteResourceGroup(getOverlord(), newGroup.getId()); + } + deleteNewResourceAgentResourceType(newResource); + + super.afterMethod(); + } + public void testResourceLineage() throws Exception { // given a resource id for the leaf resource in a resource hierarchy int leafResourceId = givenASampleResourceHierarchy(); @@ -162,7 +187,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { // Make sure our application exceptions are not wrapped public void bz886850Test() { try { - resourceManager.getResourceById(overlord, 2637426); + resourceManager.getResourceById(getOverlord(), 2637426); fail("Should have thrown a ResourceNotFoundException"); } catch (Throwable t) { if (!(t instanceof ResourceNotFoundException)) { @@ -178,7 +203,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { } } try { - LookupUtil.getOperationManager().getOperationDefinition(overlord, 3456347); + LookupUtil.getOperationManager().getOperationDefinition(getOverlord(), 3456347); fail("Should have thrown a OperationDefinitionNotFoundException"); } catch (Throwable t) { if (!(t instanceof OperationDefinitionNotFoundException)) { @@ -186,7 +211,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { } } try { - LookupUtil.getResourceTypeManager().getResourceTypeById(overlord, 3456347); + LookupUtil.getResourceTypeManager().getResourceTypeById(getOverlord(), 3456347); fail("Should have thrown a ResourceTypeNotFoundException"); } catch (Throwable t) { if (!(t instanceof ResourceTypeNotFoundException)) { @@ -194,7 +219,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { } } try { - LookupUtil.getResourceGroupManager().getResourceGroup(overlord, 3456347); + LookupUtil.getResourceGroupManager().getResourceGroup(getOverlord(), 3456347); fail("Should have thrown a ResourceGroupNotFoundException"); } catch (Throwable t) { if (!(t instanceof ResourceGroupNotFoundException)) { @@ -215,7 +240,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { ResourceGroupCriteria criteria = new ResourceGroupCriteria(); criteria.addFilterId(newGroup.getId()); criteria.fetchExplicitResources(true); - PageList<ResourceGroup> persistedGroups = groupManager.findResourceGroupsByCriteria(overlord, criteria); + PageList<ResourceGroup> persistedGroups = groupManager.findResourceGroupsByCriteria(getOverlord(), criteria); assertEquals("There should be just one group with id " + newGroup.getId(), 1, persistedGroups.size());
@@ -226,8 +251,8 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { .getExplicitResources().size());
// add resource to group - groupManager.addResourcesToGroup(overlord, newGroup.getId(), new int[] { newResource.getId() }); - persistedGroups = groupManager.findResourceGroupsByCriteria(overlord, criteria); + groupManager.addResourcesToGroup(getOverlord(), newGroup.getId(), new int[] { newResource.getId() }); + persistedGroups = groupManager.findResourceGroupsByCriteria(getOverlord(), criteria); assertEquals("There should be one member in the newly created group.", 1, persistedGroups.get(0).getExplicitResources() .size()); } @@ -237,41 +262,110 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { ResourceGroupCriteria criteria = new ResourceGroupCriteria(); criteria.addFilterId(newGroup.getId()); criteria.fetchExplicitResources(true); - PageList<ResourceGroup> persistedGroups = groupManager.findResourceGroupsByCriteria(overlord, criteria); + PageList<ResourceGroup> persistedGroups = groupManager.findResourceGroupsByCriteria(getOverlord(), criteria); assertEquals("There should be just one group with id " + newGroup.getId(), 1, persistedGroups.size()); assertEquals("An empty group is considered as MIXED.", GroupCategory.MIXED, persistedGroups.get(0) .getGroupCategory());
// add resource to group - groupManager.addResourcesToGroup(overlord, persistedGroups.get(0).getId(), new int[] { newResource.getId() }); - persistedGroups = groupManager.findResourceGroupsByCriteria(overlord, criteria); + groupManager.addResourcesToGroup(getOverlord(), persistedGroups.get(0).getId(), new int[] { newResource.getId() }); + persistedGroups = groupManager.findResourceGroupsByCriteria(getOverlord(), criteria); assertEquals("A group with just one explicit member is considered as COMPATIBLE.", GroupCategory.COMPATIBLE, persistedGroups.get(0).getGroupCategory());
// now uninventorize the only resource - resourceManager.uninventoryResource(overlord, newResource.getId()); - persistedGroups = groupManager.findResourceGroupsByCriteria(overlord, criteria); + resourceManager.uninventoryResource(getOverlord(), newResource.getId()); + persistedGroups = groupManager.findResourceGroupsByCriteria(getOverlord(), criteria); assertEquals("An empty group is considered as MIXED.", GroupCategory.MIXED, persistedGroups.get(0) .getGroupCategory()); }
public void testResourceRemovalFromGroup() { - ResourceGroup persistedGroup = groupManager.getResourceGroup(overlord, newGroup.getId()); + ResourceGroup persistedGroup = groupManager.getResourceGroup(getOverlord(), newGroup.getId()); assertEquals("An empty group is considered as MIXED.", GroupCategory.MIXED, persistedGroup.getGroupCategory());
// add resource to group - groupManager.addResourcesToGroup(overlord, persistedGroup.getId(), new int[] { newResource.getId() }); - persistedGroup = groupManager.getResourceGroup(overlord, newGroup.getId()); + groupManager.addResourcesToGroup(getOverlord(), persistedGroup.getId(), new int[] { newResource.getId() }); + persistedGroup = groupManager.getResourceGroup(getOverlord(), newGroup.getId()); assertEquals("A group with just one explicit member is considered as COMPATIBLE.", GroupCategory.COMPATIBLE, persistedGroup.getGroupCategory());
// now remove the only resource from the group - groupManager.removeResourcesFromGroup(overlord, persistedGroup.getId(), new int[] { newResource.getId() }); - persistedGroup = groupManager.getResourceGroup(overlord, newGroup.getId()); + groupManager.removeResourcesFromGroup(getOverlord(), persistedGroup.getId(), new int[] { newResource.getId() }); + persistedGroup = groupManager.getResourceGroup(getOverlord(), newGroup.getId()); assertEquals("An empty group is considered as MIXED.", GroupCategory.MIXED, persistedGroup.getGroupCategory()); }
+ public void testLiveAvailability() throws Exception { + agentServiceContainer.discoveryService = Mockito.mock(DiscoveryAgentService.class); + + Mockito.when(agentServiceContainer.discoveryService.getCurrentAvailability(Mockito.any(Resource.class))).then( + new Answer<Availability>() { + int count = 0; + + @Override + public Availability answer(InvocationOnMock invocation) throws Throwable { + Resource res = (Resource) invocation.getArguments()[0]; + AvailabilityType avail = count++ == 0 ? AvailabilityType.DOWN : AvailabilityType.UP; + return new Availability(res, avail); + } + }); + + AlertDefinition alertDef = new AlertDefinition(); + + AlertCondition cond = new AlertCondition(alertDef, AlertConditionCategory.AVAILABILITY); + cond.setName(AlertConditionOperator.AVAIL_GOES_UP.name()); + alertDef.setName("liveAvailabilityTestAlert"); + alertDef.setResource(newResource); + alertDef.setPriority(AlertPriority.MEDIUM); + alertDef.setRecoveryId(0); + alertDef.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE)); + alertDef.setConditions(Collections.singleton(cond)); + alertDef.setEnabled(true); + alertDef.setConditionExpression(BooleanExpression.ALL); + + AlertDefinitionManagerLocal alertDefinitionManager = LookupUtil.getAlertDefinitionManager(); + alertDefinitionManager.createAlertDefinitionInNewTransaction(getOverlord(), alertDef, newResource.getId(), true); + + //obvious, right? This needs to be done for the alert subsystem to become aware of the new def + LookupUtil.getAlertConditionCacheManager().reloadAllCaches(); + + ResourceCriteria crit = new ResourceCriteria(); + crit.addFilterId(newResource.getId()); + crit.fetchCurrentAvailability(true); + Resource fromDb = resourceManager.findResourcesByCriteria(getOverlord(), crit).get(0); + + assertEquals(AvailabilityType.UNKNOWN, fromDb.getCurrentAvailability().getAvailabilityType()); + + //ask for the live avail - the mock agent response will return "DOWN" the first time + resourceManager.getLiveResourceAvailability(getOverlord(), newResource.getId()); + + //check that the resource changed its avail in the db + fromDb = resourceManager.getResource(getOverlord(), newResource.getId()); + assertEquals(AvailabilityType.DOWN, fromDb.getCurrentAvailability().getAvailabilityType()); + + //ask for the live avail - the mock agent response will return "UP" the second time + resourceManager.getLiveResourceAvailability(getOverlord(), newResource.getId()); + + // wait for our JMS messages to process and see if we get any alerts + Thread.sleep(3000); + + //check that the resource changed its avail in the db + fromDb = resourceManager.getResource(getOverlord(), newResource.getId()); + assertEquals(AvailabilityType.UP, fromDb.getCurrentAvailability().getAvailabilityType()); + + // wait for our JMS messages to process and see if we get any alerts + Thread.sleep(3000); + + //check that the alert fired when going from DOWN to UP + AlertCriteria aCrit = new AlertCriteria(); + aCrit.addFilterResourceIds(newResource.getId()); + + List<Alert> alerts = LookupUtil.getAlertManager().findAlertsByCriteria(getOverlord(), aCrit); + assertEquals("Unexpected number of alerts on the resource.", 1, alerts.size()); + } + private int givenASampleResourceHierarchy() throws NotSupportedException, SystemException { getTransactionManager().begin();
@@ -339,15 +433,14 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
em.persist(resourceType);
- Agent agent = new Agent("testagent", "testaddress", 16163, "", "testtoken"); - em.persist(agent); - em.flush(); - resource = new Resource("reskey" + System.currentTimeMillis(), "resname", resourceType); + setUpAgent(resource); + resource.setUuid("" + new Random().nextInt()); - resource.setAgent(agent); resource.setInventoryStatus(InventoryStatus.COMMITTED); em.persist(resource); + + createServerIdentity(); } catch (Exception e) { System.out.println("CANNOT PREPARE TEST: " + e); getTransactionManager().rollback(); @@ -361,7 +454,7 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase {
private ResourceGroup createNewGroup() { ResourceGroup group = new ResourceGroup("testGroup"); - groupManager.createResourceGroup(overlord, group); + groupManager.createResourceGroup(getOverlord(), group); return group; }
@@ -372,9 +465,9 @@ public class ResourceManagerBeanTest extends UpdatePluginMetadataTestBase { try { Resource res = em.find(Resource.class, resource.getId()); System.out.println("Removing " + res + "..."); - List<Integer> deletedIds = resourceManager.uninventoryResource(overlord, res.getId()); + List<Integer> deletedIds = resourceManager.uninventoryResource(getOverlord(), res.getId()); for (Integer deletedResourceId : deletedIds) { - resourceManager.uninventoryResourceAsyncWork(overlord, deletedResourceId); + resourceManager.uninventoryResourceAsyncWork(getOverlord(), deletedResourceId); } em.flush();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java index 09133ae..3c1232d 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/measurement/MeasurementDataManagerBean.java @@ -832,6 +832,11 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal, } }
+ if (result != null && !result.isEmpty()) { + //we just got data from the agent so let's push them through the alerting + pushToAlertSubsystem(result); + } + //[BZ 760139] always return non-null value even when there are errors on the server side. Avoids cryptic // Global UI Exceptions when attempting to serialize null responses. if (null == result) { @@ -881,6 +886,13 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal, } } } + + if (values != null && !values.isEmpty()) { + //we just got data from the agent so let's push them through the alerting + pushToAlertSubsystem(values); + } + + return values; }
@@ -977,4 +989,17 @@ public class MeasurementDataManagerBean implements MeasurementDataManagerLocal, private MeasurementDataManagerUtility getConnectedUtilityInstance() { return MeasurementDataManagerUtility.getInstance(rhqDs); } + + private void pushToAlertSubsystem(Set<MeasurementData> data) { + MeasurementReport fakeReport = new MeasurementReport(); + for(MeasurementData datum : data) { + if (datum instanceof MeasurementDataTrait) { + fakeReport.addData((MeasurementDataTrait) datum); + } else if (datum instanceof MeasurementDataNumeric) { + fakeReport.addData((MeasurementDataNumeric) datum); + } + } + + this.measurementDataManager.mergeMeasurementReport(fakeReport); + } } 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 0aa09a4..b92548f 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 @@ -128,6 +128,7 @@ import org.rhq.enterprise.server.authz.PermissionException; import org.rhq.enterprise.server.authz.RequiredPermission; import org.rhq.enterprise.server.core.AgentManagerLocal; import org.rhq.enterprise.server.discovery.DiscoveryServerServiceImpl; +import org.rhq.enterprise.server.measurement.AvailabilityManagerLocal; import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal; import org.rhq.enterprise.server.resource.disambiguation.DisambiguationUpdateStrategy; import org.rhq.enterprise.server.resource.disambiguation.Disambiguator; @@ -172,6 +173,8 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage @EJB //@IgnoreDependency private MeasurementScheduleManagerLocal measurementScheduleManager; + @EJB + private AvailabilityManagerLocal availabilityManager;
public void createResource(Subject user, Resource resource, int parentId) throws ResourceAlreadyExistsException { Resource parent = null; @@ -2436,18 +2439,19 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage return getResourceById(subject, resourceId); }
+ @Override + @TransactionAttribute(TransactionAttributeType.NEVER) public ResourceAvailability getLiveResourceAvailability(Subject subject, int resourceId) { Resource res = getResourceById(subject, resourceId); ResourceAvailability results = new ResourceAvailability(res, AvailabilityType.UNKNOWN);
try { - Agent agent = res.getAgent(); - if (agent == null) { + // first, quickly see if we can even ping the agent, if not, don't bother trying to get the resource avail + AgentClient client = agentManager.getAgentClient(subject, res.getId()); + if (client == null) { throw new IllegalStateException("No agent is associated with the resource with id [" + resourceId + "]"); }
- // first, quickly see if we can even ping the agent, if not, don't bother trying to get the resource avail - AgentClient client = agentManager.getAgentClient(agent); boolean agentPing = client.ping(5000L); if (agentPing) { // we can't serialize the resource due to the hibernate proxies (agent can't deserialize hibernate objs) @@ -2458,10 +2462,17 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage Availability avail = client.getDiscoveryAgentService().getCurrentAvailability(bareResource); if (avail != null) { results.setAvailabilityType(avail.getAvailabilityType()); + + AvailabilityReport report = new AvailabilityReport(true, client.getAgent().getName()); + avail.setStartTime(System.currentTimeMillis()); + report.addAvailability(avail); + availabilityManager.mergeAvailabilityReport(report); } - entityManager.flush(); } - } catch (Throwable ignore) { + } catch (Exception e) { + if (log.isInfoEnabled()) { + log.info("Failed to get live availability.", e); + } }
return results;
commit 41e4393d4d2bdaf48f90a40f9379db1ecc8d2ec7 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Aug 15 10:41:28 2013 +0200
Get dbupgrade to work again.
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 9bfdb46..ddc5de9 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -1291,7 +1291,7 @@ ALTER TABLE RHQ_OPERATION_SCHEDULE ADD PRIMARY KEY (ID) </statement> </schema-directSQL> - <schema-directSQL ignoreError="true"> + <schema-directSQL ignoreError="true"> <statement desc="Changing primary key of RHQ_OPERATION_SCHEDULE to ID. Step3/3..."> CREATE UNIQUE INDEX RHQ_OPERATION_SCHEDULE_KEY_IDX ON RHQ_OPERATION_SCHEDULE (JOB_NAME, JOB_GROUP) </statement> @@ -1373,7 +1373,7 @@ <schema-directSQL> <statement> INSERT INTO RHQ_PERMISSION (role_id, operation) - SELECT role_id, 15 FROM RHQ_PERMISSION WHERE operation = 1 AND NOT role_id = 2 + SELECT role_id, 15 FROM RHQ_PERMISSION WHERE operation = 1 AND NOT role_id = 2 </statement> </schema-directSQL> </schemaSpec> @@ -1469,11 +1469,11 @@ <schema-addColumn table="RHQ_DRIFT_CONFIG" column="NAME" columnType="VARCHAR2" precision="512" /> <schema-alterColumn table="RHQ_DRIFT_CONFIG" column="NAME" nullable="FALSE" /> <schema-addColumn table="RHQ_DRIFT_CONFIG" column="INTERVAL" columnType="LONG" /> - <schema-alterColumn table="RHQ_DRIFT_CONFIG" column="INTERVAL" nullable="FALSE" /> + <schema-alterColumn table="RHQ_DRIFT_CONFIG" column="INTERVAL" nullable="FALSE" /> <schema-addColumn table="RHQ_DRIFT_CONFIG" column="IS_ENABLED" columnType="BOOLEAN" /> <schema-alterColumn table="RHQ_DRIFT_CONFIG" column="IS_ENABLED" nullable="FALSE" /> <schema-addColumn table="RHQ_DRIFT_CONFIG" column="CONFIG_ID" columnType="INTEGER" /> - <schema-alterColumn table="RHQ_DRIFT_CONFIG" column="CONFIG_ID" nullable="FALSE" /> + <schema-alterColumn table="RHQ_DRIFT_CONFIG" column="CONFIG_ID" nullable="FALSE" /> <schema-directSQL> <statement desc="Creating RHQ_DRIFT_CONFIG foreign key relation to RHQ_CONFIG"> ALTER TABLE RHQ_DRIFT_CONFIG @@ -1482,7 +1482,7 @@ REFERENCES RHQ_CONFIG (ID) </statement> </schema-directSQL> - <schema-addColumn table="RHQ_DRIFT_CONFIG" column="RESOURCE_ID" columnType="INTEGER" /> + <schema-addColumn table="RHQ_DRIFT_CONFIG" column="RESOURCE_ID" columnType="INTEGER" /> <schema-directSQL> <statement desc="Creating RHQ_DRIFT_CONFIG foreign key relation to RHQ_RESOURCE"> ALTER TABLE RHQ_DRIFT_CONFIG @@ -1492,7 +1492,7 @@ </statement> </schema-directSQL>
- + <!-- RHQ_DRIFT_CHANGE_SET --> <schema-createSequence name="RHQ_DRIFT_CHANGE_SET_ID_SEQ" initial="10001" /> <schema-directSQL> @@ -1507,7 +1507,7 @@ <schema-addColumn table="RHQ_DRIFT_CHANGE_SET" column="CATEGORY" columnType="VARCHAR2" precision="20" /> <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="CATEGORY" nullable="FALSE" /> <schema-addColumn table="RHQ_DRIFT_CHANGE_SET" column="RESOURCE_ID" columnType="INTEGER" /> - <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="RESOURCE_ID" nullable="FALSE" /> + <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="RESOURCE_ID" nullable="FALSE" /> <schema-directSQL> <statement desc="Creating RHQ_DRIFT_CHANGE_SET foreign key relation to RHQ_RESOURCE"> ALTER TABLE RHQ_DRIFT_CHANGE_SET @@ -1515,9 +1515,9 @@ FOREIGN KEY (RESOURCE_ID) REFERENCES RHQ_RESOURCE (ID) </statement> - </schema-directSQL> + </schema-directSQL> <schema-addColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_CONFIG_ID" columnType="INTEGER" /> - <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_CONFIG_ID" nullable="FALSE" /> + <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_CONFIG_ID" nullable="FALSE" /> <schema-directSQL> <statement desc="Creating RHQ_DRIFT_CHANGE_SET foreign key relation to RHQ_DRIFT_CONFIG"> ALTER TABLE RHQ_DRIFT_CHANGE_SET @@ -1631,10 +1631,10 @@ <!-- RHQ 4.2 RELEASE uses DB Schema 2.114 Note, the 4.1 to 4.2 upgrade is broken because a 4.2 dbsetup actually creates a 2.115 schema. So, for 4.2 dbs to upgrade to 4.3 the schema version must first be corrected and set the schema - version to 2.115. + version to 2.115. -->
- <schemaSpec version="2.115"> + <schemaSpec version="2.115"> <!-- RHQ_DRIFT_DEF_TEMPLATE --> <schema-createSequence name="RHQ_DRIFT_DEF_TEMPLATE_ID_SEQ" initial="10001" /> <schema-directSQL> @@ -1654,7 +1654,7 @@ <schema-addColumn table="RHQ_DRIFT_DEF_TEMPLATE" column="CTIME" columnType="LONG" /> <schema-alterColumn table="RHQ_DRIFT_DEF_TEMPLATE" column="CTIME" nullable="FALSE" /> <schema-addColumn table="RHQ_DRIFT_DEF_TEMPLATE" column="IS_USER_DEFINED" columnType="BOOLEAN" /> - <schema-alterColumn table="RHQ_DRIFT_DEF_TEMPLATE" column="IS_USER_DEFINED" nullable="FALSE" /> + <schema-alterColumn table="RHQ_DRIFT_DEF_TEMPLATE" column="IS_USER_DEFINED" nullable="FALSE" /> <schema-directSQL> <statement desc="Creating RHQ_DRIFT_DEF_TEMPLATE foreign key to RHQ_RESOURCE_TYPE"> ALTER TABLE RHQ_DRIFT_DEF_TEMPLATE @@ -1676,7 +1676,7 @@ </schema-directSQL>
<!-- RHQ_DRIFT_CONFIG => RHQ_DRIFT_DEFINITION --> - <schema-directSQL> + <schema-directSQL> <statement> ALTER TABLE RHQ_DRIFT_CONFIG RENAME TO RHQ_DRIFT_DEFINITION </statement> @@ -1685,17 +1685,17 @@ </statement> <statement targetDBVendor="oracle"> RENAME RHQ_DRIFT_CONFIG_ID_SEQ TO RHQ_DRIFT_DEFINITION_ID_SEQ - </statement> + </statement> </schema-directSQL>
<!-- add new columns --> - <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DESCRIPTION" columnType="VARCHAR2" precision="512" /> + <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DESCRIPTION" columnType="VARCHAR2" precision="512" /> <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DRIFT_HANDLING_MODE" columnType="VARCHAR2" precision="20" /> <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="IS_PINNED" columnType="BOOLEAN"/> <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="IS_ATTACHED" columnType="BOOLEAN"/> <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="DRIFT_DEF_TEMPLATE_ID" columnType="INTEGER"/> - - <!-- initialize new required columns --> + + <!-- initialize new required columns --> <schema-directSQL> <statement targetDBVendor="postgresql" desc="RHQ_DRIFT_DEFINITION: set is_pinned column (false)"> UPDATE RHQ_DRIFT_DEFINITION SET IS_PINNED = FALSE @@ -1712,9 +1712,9 @@ <statement desc="RHQ_DRIFT_DEFINITION: set drift_handling_mode column (normal)"> UPDATE RHQ_DRIFT_DEFINITION SET DRIFT_HANDLING_MODE = 'normal' </statement> - </schema-directSQL> + </schema-directSQL> <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="IS_PINNED" nullable="FALSE"/> - <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="IS_ATTACHED" nullable="FALSE"/> + <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="IS_ATTACHED" nullable="FALSE"/> <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="DRIFT_HANDLING_MODE" nullable="FALSE" />
<!-- add new FK --> @@ -1740,7 +1740,7 @@ <!-- RHQ_DRIFT_CHANGE_SET --> <!-- Resource column is now nullable --> <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="RESOURCE_ID" nullable="TRUE" /> - + <!-- Add new drift_set column with FK --> <schema-addColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_SET_ID" columnType="INTEGER"/> <schema-directSQL> @@ -1750,9 +1750,9 @@ FOREIGN KEY (DRIFT_SET_ID) REFERENCES RHQ_DRIFT_SET (ID) </statement> - </schema-directSQL> + </schema-directSQL> +
- <!-- Rename column DRIFT_CONFIG_ID to DRIFT_DEFINITION_ID --> <schema-directSQL> <statement desc="Renaming RHQ_DRIFT_CHANGE_SET.DRIFT_CONFIG_ID column to DRIFT_DEFINITION_ID"> @@ -1768,20 +1768,20 @@ <statement desc="RHQ_DRIFT_CHANGE_SET: set drift_handling_mode column (normal)"> UPDATE RHQ_DRIFT_CHANGE_SET SET DRIFT_HANDLING_MODE = 'normal' </statement> - </schema-directSQL> + </schema-directSQL> <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_HANDLING_MODE" nullable="FALSE" />
<!-- RHQ_DRIFT --> - <!-- Add new path_directory column --> + <!-- Add new path_directory column --> <schema-addColumn table="RHQ_DRIFT" column="PATH_DIRECTORY" columnType="VARCHAR2" precision="1024" /> - + <!-- Set the new path_directory column using the current path column values --> - <schema-javaTask className="DriftPathDirectoryDatabaseUpgradeTask" /> + <schema-javaTask className="DriftPathDirectoryDatabaseUpgradeTask" />
<!-- Now it is safe to set the new path_directory column not null --> - <schema-alterColumn table="RHQ_DRIFT" column="PATH_DIRECTORY" nullable="FALSE" /> - + <schema-alterColumn table="RHQ_DRIFT" column="PATH_DIRECTORY" nullable="FALSE" /> + <!-- add new drift_set_id column and FK --> <schema-addColumn table="RHQ_DRIFT" column="DRIFT_SET_ID" columnType="INTEGER"/> <schema-directSQL> @@ -1795,48 +1795,48 @@
<!-- Morph rhq_drift_template_map rows into rhq_drift_def_template rows. The rhq_drift_template_map table is obsolete. --> - <schema-javaTask className="DriftTemplateMapDatabaseUpgradeTask" /> + <schema-javaTask className="DriftTemplateMapDatabaseUpgradeTask" />
</schemaSpec>
<!-- RHQ 4.2 RELEASE uses DB Schema 2.114, which is incorrect, it should have been 2.115. So, for the upgrade to work for an RHQ 4.2 install the schema version must be set to 2.115 prior to the upgrade. - + The 4.2 upgrade should start with 2.116. --> <schemaSpec version="2.116"> - <!-- RHQ_DRIFT_DEFINITION changes --> + <!-- RHQ_DRIFT_DEFINITION changes --> <schema-addColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" columnType="INTEGER"/> <schema-directSQL> <statement desc="RHQ_DRIFT_DEFINITION: set compliance_status column (in compliance)"> UPDATE RHQ_DRIFT_DEFINITION SET COMPLIANCE_STATUS = 0 </statement> </schema-directSQL> - <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" nullable="FALSE"/> - + <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="COMPLIANCE_STATUS" nullable="FALSE"/> + <schema-alterColumn table="RHQ_DRIFT_DEFINITION" column="NAME" columnType="VARCHAR2" precision="512" /> - - - <!-- RHQ_PRD_VER changes --> + + + <!-- RHQ_PRD_VER changes --> <!-- Increase the max length of a product version from 50 to 100. --> <schema-alterColumn table="RHQ_PRD_VER" column="VERSION" columnType="VARCHAR2" precision="100" /> </schemaSpec>
<!-- JON 3.0 RELEASE uses DB Schema 2.116 --> - + <schemaSpec version="2.117"> <!-- Remove an obsolete drift table that may be hanging around --> <schema-dropTable table="RHQ_DRIFT_TEMPLATE_MAP" ignoreError="true" /> - + <!-- Remove an unwanted null constraint --> - <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_DEFINITION_ID" nullable="TRUE" /> + <schema-alterColumn table="RHQ_DRIFT_CHANGE_SET" column="DRIFT_DEFINITION_ID" nullable="TRUE" /> </schemaSpec>
<schemaSpec version="2.118"> <!-- Correct an earlier upgrade issue where 'All Resources Role' was granted MANAGE_REPOSITORIES. --> <schema-directSQL> <statement> - DELETE FROM RHQ_PERMISSION WHERE role_id = 2 AND operation = 15 + DELETE FROM RHQ_PERMISSION WHERE role_id = 2 AND operation = 15 </statement> </schema-directSQL> </schemaSpec> @@ -1849,42 +1849,42 @@ </statement> </schema-directSQL> </schemaSpec> - + <schemaSpec version="2.120"> - <!-- RHQ_AGENT changes --> + <!-- RHQ_AGENT changes --> <schema-addColumn table="RHQ_AGENT" column="LAST_AVAILABILITY_PING" columnType="LONG"/> <schema-directSQL> <statement desc="RHQ_AGENT: init last_availability_ping to last_availability_report"> - UPDATE RHQ_AGENT SET LAST_AVAILABILITY_PING = LAST_AVAILABILITY_REPORT + UPDATE RHQ_AGENT SET LAST_AVAILABILITY_PING = LAST_AVAILABILITY_REPORT </statement> </schema-directSQL>
<!-- Drop agent quiet time (i.e. suspect agent time) from 15 to 5 minutes --> <schema-directSQL> <statement desc="Changing AGENT_MAX_QUIET_TIME_ALLOWED to 5 minutes from 15 minutes"> - UPDATE RHQ_SYSTEM_CONFIG - SET PROPERTY_VALUE = '300000', DEFAULT_PROPERTY_VALUE = '300000' + UPDATE RHQ_SYSTEM_CONFIG + SET PROPERTY_VALUE = '300000', DEFAULT_PROPERTY_VALUE = '300000' WHERE PROPERTY_KEY = 'AGENT_MAX_QUIET_TIME_ALLOWED' </statement> </schema-directSQL> - + <!-- set null availabilities to UNKNOWN --> <schema-directSQL> <statement desc="Changing NULL RHQ_AVAILABILITY.AVAILABILITY_TYPE to UNKNOWN"> UPDATE RHQ_AVAILABILITY - SET AVAILABILITY_TYPE = 2 + SET AVAILABILITY_TYPE = 2 WHERE AVAILABILITY_TYPE IS NULL </statement> <statement desc="Changing NULL RHQ_RESOURCE_AVAIL.AVAILABILITY_TYPE to UNKNOWN"> UPDATE RHQ_RESOURCE_AVAIL - SET AVAILABILITY_TYPE = 2 + SET AVAILABILITY_TYPE = 2 WHERE AVAILABILITY_TYPE IS NULL </statement> </schema-directSQL>
<schema-alterColumn table="RHQ_AVAILABILITY" column="AVAILABILITY_TYPE" nullable="FALSE"/> - <schema-alterColumn table="RHQ_RESOURCE_AVAIL" column="AVAILABILITY_TYPE" nullable="FALSE"/> - + <schema-alterColumn table="RHQ_RESOURCE_AVAIL" column="AVAILABILITY_TYPE" nullable="FALSE"/> + </schemaSpec>
<schemaSpec version="2.121"> @@ -1892,27 +1892,27 @@ </schemaSpec>
<!-- RHQ 4.4, JON 3.1.0 RELEASE uses DB Schema 2.121 --> - + <schemaSpec version="2.122"> - <schema-directSQL> + <schema-directSQL> <statement desc="Updating DOWN Alert Conditions to new format"> UPDATE RHQ_ALERT_CONDITION SET NAME = 'AVAIL_GOES_DOWN', OPTION_STATUS = NULL - WHERE TYPE = 'AVAILABILITY' + WHERE TYPE = 'AVAILABILITY' AND NAME IS NULL AND OPTION_STATUS = 'DOWN' </statement> <statement desc="Updating UP Alert Conditions to new format"> UPDATE RHQ_ALERT_CONDITION - SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL + SET NAME = 'AVAIL_GOES_UP', OPTION_STATUS = NULL WHERE TYPE = 'AVAILABILITY' AND NAME IS NULL AND OPTION_STATUS = 'UP' - </statement> - </schema-directSQL> + </statement> + </schema-directSQL> </schemaSpec> - -<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 --> + +<!-- JON 3.1.1 RELEASE uses DB Schema 2.122 -->
<schemaSpec version="2.123">
@@ -1989,8 +1989,8 @@ </schema-directSQL> </schemaSpec>
-<!-- RHQ 4.6.0 uses DB Schema 2.128 --> - +<!-- RHQ 4.6.0 uses DB Schema 2.128 --> + <!-- BZ 881848 --> <schemaSpec version="2.129"> <schema-directSQL> @@ -2080,12 +2080,12 @@
<schemaSpec version="2.135"> <!-- Fine Grained Bundle Permissions --> - + <!-- Add new perms to superuser/all-resources roles --> <schema-directSQL> <statement desc="Inserting MANAGE_BUNDLE_GROUPS permission for all MANAGE_BUNDLE (12) roles"> INSERT INTO rhq_permission (role_id, operation) SELECT role_id, 18 FROM rhq_permission p where p.operation = 12 - </statement> + </statement> <statement desc="Inserting CREATE_BUNDLES permission for all MANAGE_BUNDLE (12) roles"> INSERT INTO rhq_permission (role_id, operation) SELECT role_id, 19 FROM rhq_permission p where p.operation = 12 </statement> @@ -2181,6 +2181,13 @@
<schemaSpec version="2.136"> <schema-addColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" columnType="VARCHAR2" precision="12"/> + <schema-directSQL> + <statement desc="Fill in defaults"> + UPDATE RHQ_CONFIG_PD_OSRC + SET EXPRESSION_SCOPE = 'unlimited' + WHERE EXPRESSION_SCOPE IS NULL + </statement> + </schema-directSQL> <schema-alterColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" nullable="false" default="unlimited"/> </schemaSpec>
@@ -2196,10 +2203,10 @@ REFERENCES RHQ_OPERATION_HISTORY (ID) </statement> <statement targetDBVendor="postgresql" desc="Set maintenance_pending flag to false for existing storage nodes"> - UPDATE RHQ_STORAGE_NODE SET IGNORED = false + UPDATE RHQ_STORAGE_NODE SET MAINTENANCE_PENDING = false </statement> <statement targetDBVendor="oracle" desc="Set maintenance_pending flag to false for existing storage nodes"> - UPDATE RHQ_STORAGE_NODE SET IGNORED = 0 + UPDATE RHQ_STORAGE_NODE SET MAINTENANCE_PENDING = 0 </statement> </schema-directSQL> </schemaSpec>
commit 32e9b5637e04d194feb505244166fc22f56c7f7f Author: Heiko W. Rupp hwr@redhat.com Date: Tue Aug 13 15:57:01 2013 +0200
BZ 996276 Fix example expressions
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java index 9678629..3a216a2 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/trigger/JobTriggerEditor.java @@ -306,8 +306,8 @@ public class JobTriggerEditor extends EnhancedVLayout { + " </tbody>\n" + "\n" + "</table>\n" - + "<p>So cron expressions can be as simple as this: <tt>* * * * ? *</tt><br />\n" - + "or more complex, like this: <tt>0/5 14,18,3-39,52 * ? JAN,MAR,SEP MON-FRI 2002-2010</tt></p>\n" + + "<p>So cron expressions can be as simple as this: <tt>0 * * ? * *</tt> to run every minute on the minute<br />\n" + + "or more complex, like this: <tt>0/5 14,18,3-39,52 * ? JAN,MAR,SEP MON-FRI 2002-2015</tt></p>\n" + "\n" + "<h2><a name="CronTriggersTutorial-Specialcharacters"></a>Special Characters</h2>\n" + "\n"
commit 3d2f1df19ea239cb963b8091d6267bf101144708 Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 01:57:08 2013 -0400
removing unused exception class
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageConfigurationException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageConfigurationException.java deleted file mode 100644 index dc616a8..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageConfigurationException.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.rhq.enterprise.server.storage; - -/** - * @author John Sanda - */ -public class StorageConfigurationException extends RuntimeException { - - public StorageConfigurationException() { - super(); - } - - public StorageConfigurationException(String message) { - super(message); - } - - public StorageConfigurationException(String message, Throwable cause) { - super(message, cause); - } - - public StorageConfigurationException(Throwable cause) { - super(cause); - } -}
commit 29f46961735b2724f517358b6198b6d909e0a7cb Author: John Sanda jsanda@redhat.com Date: Thu Aug 15 01:56:04 2013 -0400
add maintenance flag for queueing up storage nodes to be processed
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml index f307ff8..da9ff04 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml @@ -455,6 +455,7 @@ <column name="CTIME" required="true" type="LONG" /> <column name="MTIME" required="true" type="LONG" /> <column name="ERROR_MSG" required="false" type="LONGVARCHAR"/> + <column name="MAINTENANCE_PENDING" required="true" type="BOOLEAN" default="false"/> <column name="RESOURCE_ID" required="false" type="INTEGER" references="RHQ_RESOURCE(ID)" /> <column name="RESOURCE_OP_HIST_ID" required="false" type="INTEGER" references="RHQ_OPERATION_HISTORY(ID)"/>
diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index edf0147..9bfdb46 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2185,6 +2185,7 @@ </schemaSpec>
<schemaSpec version="2.137"> + <schema-addColumn table="RHQ_STORAGE_NODE" column="MAINTENANCE_PENDING" columnType="BOOLEAN"/> <schema-addColumn table="RHQ_STORAGE_NODE" column="ERROR_MSG" columnType="LONGVARCHAR"/> <schema-addColumn table="RHQ_STORAGE_NODE" column="RESOURCE_OP_HIST_ID" columnType="INTEGER"/> <schema-directSQL> @@ -2194,6 +2195,12 @@ FOREIGN KEY (RESOURCE_OP_HIST_ID) REFERENCES RHQ_OPERATION_HISTORY (ID) </statement> + <statement targetDBVendor="postgresql" desc="Set maintenance_pending flag to false for existing storage nodes"> + UPDATE RHQ_STORAGE_NODE SET IGNORED = false + </statement> + <statement targetDBVendor="oracle" desc="Set maintenance_pending flag to false for existing storage nodes"> + UPDATE RHQ_STORAGE_NODE SET IGNORED = 0 + </statement> </schema-directSQL> </schemaSpec>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index 3f2a89c..54a0db5 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -135,6 +135,9 @@ public class StorageNode implements Serializable { @Column(name = "MTIME", nullable = false) private long mtime;
+ @Column(name = "MAINTENANCE_PENDING", nullable = false) + private boolean maintenancePending; + @Column(name = "ERROR_MSG", nullable = true) private String errorMessage;
@@ -198,6 +201,14 @@ public class StorageNode implements Serializable { this.mtime = mtime; }
+ public boolean isMaintenancePending() { + return maintenancePending; + } + + public void setMaintenancePending(boolean maintenancePending) { + this.maintenancePending = maintenancePending; + } + public Resource getResource() { return resource; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index 72f5e9d..2a79c59 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -84,18 +84,19 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa List<StorageNode> allNodes = new ArrayList<StorageNode>(clusterNodes); allNodes.add(storageNode);
- announceStorageNode(subject, storageNode, createPropertyListOfAddresses("addresses", allNodes), - getAddresses(clusterNodes)); + for (StorageNode clusterNode : clusterNodes) { + clusterNode.setMaintenancePending(true); + }
- } + announceStorageNode(subject, storageNode, clusterNodes.get(0), createPropertyListOfAddresses("addresses", + allNodes));
- private void announceStorageNode(Subject subject, StorageNode storageNode, PropertyList addresses, - List<String> remainingNodes) { - String address = remainingNodes.remove(0); - StorageNode clusterNode = findStorageNodeByAddress(address); + }
+ private void announceStorageNode(Subject subject, StorageNode newStorageNode, StorageNode clusterNode, + PropertyList addresses) { if (log.isInfoEnabled()) { - log.info("Announcing " + storageNode + " to cluster node " + clusterNode); + log.info("Announcing " + newStorageNode + " to cluster node " + clusterNode); } ResourceOperationSchedule schedule = new ResourceOperationSchedule(); schedule.setResource(clusterNode.getResource()); @@ -104,7 +105,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa schedule.setOperationName("updateKnownNodes"); Configuration parameters = new Configuration(); parameters.put(addresses); - parameters.put(new PropertySimple("remainingNodes", StringUtil.listToString(remainingNodes))); schedule.setParameters(parameters);
operationManager.scheduleResourceOperation(subject, schedule); @@ -141,8 +141,9 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) .getResultList(); for (StorageNode node : clusterNodes) { - node.setOperationMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + node.setMaintenancePending(true); } + storageNode.setMaintenancePending(true); clusterNodes.add(storageNode); boolean runRepair = updateSchemaIfNecessary(clusterNodes); performAddNodeMaintenance(subject, storageNode, runRepair, createPropertyListOfAddresses(SEEDS_LIST, @@ -231,19 +232,20 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa operationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS + storageNode.setMaintenancePending(false); Configuration parameters = resourceOperationHistory.getParameters(); PropertyList addresses = parameters.getList("addresses"); - List<String> remainingNodes = getRemainingNodes(resourceOperationHistory); + StorageNode nextNode = takeFromMaintenanceQueue();
newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); Subject subject = getSubject(resourceOperationHistory);
- if (remainingNodes.isEmpty()) { + if (nextNode == null) { log.info("Successfully announced new storage node to storage cluster"); newStorageNode.setOperationMode(StorageNode.OperationMode.BOOTSTRAP); prepareNodeForBootstrap(subject, newStorageNode, addresses.deepCopy(false)); } else { - announceStorageNode(subject, newStorageNode, addresses.deepCopy(false), remainingNodes); + announceStorageNode(subject, newStorageNode, nextNode, addresses.deepCopy(false)); } } } @@ -293,11 +295,14 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Finished cluster maintenance for " + storageNode + " for addition of new node"); } - storageNode.setOperationMode(StorageNode.OperationMode.NORMAL); - StorageNode nextNode = takeFromQueue(storageNode, StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + storageNode.setMaintenancePending(false); + StorageNode nextNode = takeFromMaintenanceQueue();
if (nextNode == null) { log.info("Finished running cluster maintenance for addition of new node"); + // TODO replace this with an UPDATE statement + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + newStorageNode.setOperationMode(StorageNode.OperationMode.NORMAL); } else { Configuration parameters = resourceOperationHistory.getParameters(); boolean runRepair = parameters.getSimple(RUN_REPAIR_PROPERTY).getBooleanValue(); @@ -399,33 +404,16 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa operationManager.scheduleResourceOperation(subject, schedule); }
- private StorageNode takeFromQueue(StorageNode lastTaken, StorageNode.OperationMode queue) { - List<StorageNode> nodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE_EXCLUDING, - StorageNode.class).setParameter("operationMode", queue).setParameter("storageNode", lastTaken) + private StorageNode takeFromMaintenanceQueue() { + List<StorageNode> storageNodes = entityManager.createQuery("SELECT s FROM StorageNode s WHERE " + + "s.operationMode = :operationMode AND s.maintenancePending = :maintenancePending", StorageNode.class) + .setParameter("operationMode", StorageNode.OperationMode.NORMAL).setParameter("maintenancePending", true) .getResultList();
- if (nodes.isEmpty()) { + if (storageNodes.isEmpty()) { return null; } - return nodes.get(0); - } - - private List<String> getRemainingNodes(ResourceOperationHistory resourceOperationHistory) { - LinkedList<String> addresses = new LinkedList<String>(); - Configuration results = resourceOperationHistory.getResults(); - String remainingNodes = results.getSimpleValue("remainingNodes"); - - if (!StringUtil.isEmpty(remainingNodes)) { - for (String address : remainingNodes.split(",")) { - addresses.add(address); - } - } - return addresses; - } - - private StorageNode findStorageNodeByAddress(String address) { - return entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, StorageNode.class) - .setParameter("address", address).getSingleResult(); + return storageNodes.get(0); }
private StorageNode findNewStorgeNode(StorageNode.OperationMode operationMode) { @@ -537,12 +525,4 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return list; }
- private List<String> getAddresses(List<StorageNode> storageNodes) { - List<String> addresses = new LinkedList<String>(); - for (StorageNode storageNode : storageNodes) { - addresses.add(storageNode.getAddress()); - } - return addresses; - } - } diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java index 7f58037..a24a219 100644 --- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java +++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java @@ -257,7 +257,6 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper
Configuration complexResults = result.getComplexResults(); complexResults.put(new PropertySimple("details", "Successfully updated the set of known nodes.")); - complexResults.put(params.get("remainingNodes").deepCopy(false));
return result; } catch (InternodeAuthConfUpdateException e) { diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml index 4ef10cd..cc01c9d 100644 --- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml @@ -102,11 +102,9 @@ <c:list-property name="addresses"> <c:simple-property name="address"/> </c:list-property> - <c:simple-property name="remainingNodes"/> </parameters> <results> <c:simple-property name="details"/> - <c:simple-property name="remainingNodes"/> </results> </operation>
commit b2a92a612bcd7116e51088fd15358bf9d85adb52 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 23:32:41 2013 -0400
bump up dbupgrade version
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml index 2e8e4b8..1c66dd6 100644 --- a/modules/core/dbutils/pom.xml +++ b/modules/core/dbutils/pom.xml @@ -17,7 +17,7 @@ <description>Database schema setup, upgrade and other utilities</description>
<properties> - <db.schema.version>2.136</db.schema.version> + <db.schema.version>2.137</db.schema.version> <rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping> <rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name> <rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name>
commit c13fef8af6b57a501a0d3edd5b276b8284bd71df Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 23:02:34 2013 -0400
adding more error handling for storage node deployments
In my previous commit I added code to persist resource operation failures that occur during storage node deployment. This commit adds error handling for unexpected server side errors. Errors are logged to the StorageNode entity in a separate transaction to ensure that the error message gets persisted.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java deleted file mode 100644 index fca6e96..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.rhq.enterprise.server.storage; - -/** - * @author John Sanda - */ -public class StorageNodeDeploymentException extends RuntimeException { - - public StorageNodeDeploymentException() { - } - - public StorageNodeDeploymentException(String message) { - super(message); - } - - public StorageNodeDeploymentException(String message, Throwable cause) { - super(message, cause); - } - - public StorageNodeDeploymentException(Throwable cause) { - super(cause); - } -} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index aaa54f5..72f5e9d 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -12,7 +12,6 @@ import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; -import javax.persistence.PersistenceException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -23,13 +22,13 @@ import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertySimple; -import org.rhq.core.domain.operation.OperationDefinition; import org.rhq.core.domain.operation.OperationHistory; import org.rhq.core.domain.operation.ResourceOperationHistory; import org.rhq.core.domain.operation.bean.ResourceOperationSchedule; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.util.StringUtil; +import org.rhq.core.util.exception.ThrowableUtil; import org.rhq.enterprise.server.RHQConstants; import org.rhq.enterprise.server.auth.SessionManager; import org.rhq.enterprise.server.auth.SubjectManagerLocal; @@ -71,8 +70,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa @EJB private StorageClientManagerBean storageClientManager;
+ @EJB + private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler; + @Override - @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) public void announceStorageNode(Subject subject, StorageNode storageNode) { if (log.isInfoEnabled()) { log.info("Announcing " + storageNode + " to storage node cluster."); @@ -110,6 +111,18 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
@Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void logError(StorageNode.OperationMode newStorageNodeOperationMode, String error, Exception e) { + try { + StorageNode newStorageNode = findNewStorgeNode(newStorageNodeOperationMode); + newStorageNode.setErrorMessage(error + " Check the server log for details. Root cause: " + + ThrowableUtil.getRootCause(e).getMessage()); + } catch (Exception e1) { + log.error("Failed to log error against storage node", e); + } + } + + @Override public void performAddNodeMaintenanceIfNecessary(InetAddress storageNodeAddress) { StorageNode storageNode = entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, StorageNode.class).setParameter("address", storageNodeAddress.getHostAddress()).getSingleResult(); @@ -167,24 +180,77 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return; }
- ResourceOperationHistory resourceOperationHistory = entityManager.find(ResourceOperationHistory.class, - operationHistory.getId()); - if (resourceOperationHistory == null) { + ResourceOperationHistory resourceOperationHistory = (ResourceOperationHistory) operationHistory; + if (!isStorageNodeOperation(resourceOperationHistory)) { return; }
- if (isStorageNodeOperation(resourceOperationHistory.getOperationDefinition())) { - if (resourceOperationHistory.getOperationDefinition().getName().equals("updateKnownNodes")) { - handleUpdateKnownNodes(resourceOperationHistory); - } else if (operationHistory.getOperationDefinition().getName().equals("prepareForBootstrap")) { - handlePrepareForBootstrap(resourceOperationHistory); - } else if (operationHistory.getOperationDefinition().getName().equals("addNodeMaintenance")) { - handleAddNodeMaintenance(resourceOperationHistory); + if (resourceOperationHistory.getOperationDefinition().getName().equals("updateKnownNodes")) { + try { + storageNodeOperationsHandler.handleUpdateKnownNodes(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting storage node deployment due to unexpected error while announcing cluster nodes."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.ANNOUNCE, msg, e); + } + } else if (operationHistory.getOperationDefinition().getName().equals("prepareForBootstrap")) { + try { + storageNodeOperationsHandler.handlePrepareForBootstrap(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting storage node deployment due to unexpected error while bootstrapping new node."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.BOOTSTRAP, msg, e); + } + } else if (operationHistory.getOperationDefinition().getName().equals("addNodeMaintenance")) { + try { + storageNodeOperationsHandler.handleAddNodeMaintenance(resourceOperationHistory); + } catch (Exception e) { + String msg = "Aborting storage node deployment due to unexpected error while performing add node " + + "maintenance."; + log.error(msg, e); + storageNodeOperationsHandler.logError(StorageNode.OperationMode.ADD_NODE_MAINTENANCE, msg, e); } } + }
- private void handlePrepareForBootstrap(ResourceOperationHistory resourceOperationHistory) { + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handleUpdateKnownNodes(ResourceOperationHistory resourceOperationHistory) { + StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); + StorageNode newStorageNode = null; + switch (resourceOperationHistory.getStatus()) { + case INPROGRESS: + // nothing to do here + return; + case CANCELED: + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + operationCanceled(storageNode, resourceOperationHistory, newStorageNode); + case FAILURE: + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + operationFailed(storageNode, resourceOperationHistory, newStorageNode); + return; + default: // SUCCESS + Configuration parameters = resourceOperationHistory.getParameters(); + PropertyList addresses = parameters.getList("addresses"); + List<String> remainingNodes = getRemainingNodes(resourceOperationHistory); + + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + Subject subject = getSubject(resourceOperationHistory); + + if (remainingNodes.isEmpty()) { + log.info("Successfully announced new storage node to storage cluster"); + newStorageNode.setOperationMode(StorageNode.OperationMode.BOOTSTRAP); + prepareNodeForBootstrap(subject, newStorageNode, addresses.deepCopy(false)); + } else { + announceStorageNode(subject, newStorageNode, addresses.deepCopy(false), remainingNodes); + } + } + } + + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handlePrepareForBootstrap(ResourceOperationHistory resourceOperationHistory) { StorageNode newStorageNode = findStorageNode(resourceOperationHistory.getResource()); switch (resourceOperationHistory.getStatus()) { case INPROGRESS: @@ -195,15 +261,9 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // If the operation is canceled the plugin will get an InterruptedException. // The actual bootstrapping may very well complete so we need to add in some // checks to find out if the node is up and part of the cluster. - - log.error("The operation [prepareForBootstrap] was canceled for " + newStorageNode + - ". Deployment of the new storage node cannot proceed."); operationCanceled(newStorageNode, resourceOperationHistory); return; case FAILURE: - log.error("The operation [preparedForBootstrap] failed for " + newStorageNode + ". The reported " + - "failure is: " + resourceOperationHistory.getErrorMessage()); - log.error("Deployment of the new storage node cannot proceed."); operationFailed(newStorageNode, resourceOperationHistory); return; default: // SUCCESS @@ -212,47 +272,9 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } }
- private void handleUpdateKnownNodes(ResourceOperationHistory resourceOperationHistory) { - StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); - StorageNode newStorageNode = null; - switch (resourceOperationHistory.getStatus()) { - case INPROGRESS: - // nothing to do here - return; - case CANCELED: - log.error("The operation [updateKnownNodes] was canceled for " + storageNode + - ". Deployment of the new storage node cannot proceed."); - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); - operationCanceled(storageNode, resourceOperationHistory, newStorageNode); - case FAILURE: - log.error("The operation [updateKnownNodes] failed for " + storageNode + ". The reported " + - "failure is: " + resourceOperationHistory.getErrorMessage()); - log.error("Deployment of the new storage node cannot proceed."); - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); - operationFailed(storageNode, resourceOperationHistory, newStorageNode); - return; - default: // SUCCESS - if (log.isInfoEnabled()) { - log.info("Finished announcing cluster nodes to " + storageNode); - } - Configuration parameters = resourceOperationHistory.getParameters(); - PropertyList addresses = parameters.getList("addresses"); - List<String> remainingNodes = getRemainingNodes(resourceOperationHistory); - - newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); - Subject subject = getSubject(resourceOperationHistory); - - if (remainingNodes.isEmpty()) { - log.info("Successfully announced new storage node to cluster"); - newStorageNode.setOperationMode(StorageNode.OperationMode.BOOTSTRAP); - prepareNodeForBootstrap(subject, newStorageNode, addresses.deepCopy(false)); - } else { - announceStorageNode(subject, newStorageNode, addresses.deepCopy(false), remainingNodes); - } - } - } - - private void handleAddNodeMaintenance(ResourceOperationHistory resourceOperationHistory) { + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void handleAddNodeMaintenance(ResourceOperationHistory resourceOperationHistory) { StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); StorageNode newStorageNode = null; switch (resourceOperationHistory.getStatus()) { @@ -260,21 +282,16 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // nothing to do here return; case CANCELED: - log.error("The operation [addNodeMaintenance] was canceled for " + storageNode + ". This operation " + - "needs to be run on each storage node when a new node is added to the cluster."); newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); operationCanceled(storageNode, resourceOperationHistory, newStorageNode); return; case FAILURE: - log.error("The operation [addNodeMaintenance] failed for " + storageNode + ". This operation " + - "needs to be run on each storage node when a new node is added to the cluster. The reported " + - "failure is: " + resourceOperationHistory.getErrorMessage()); newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); operationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS if (log.isInfoEnabled()) { - log.info("Finnished cluster maintenance for " + storageNode + " for addition of new node"); + log.info("Finished cluster maintenance for " + storageNode + " for addition of new node"); } storageNode.setOperationMode(StorageNode.OperationMode.NORMAL); StorageNode nextNode = takeFromQueue(storageNode, StorageNode.OperationMode.ADD_NODE_MAINTENANCE); @@ -298,6 +315,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
private void operationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, StorageNode newStorageNode) { + log.error("Deployment has been aborted due to canceled operation [" + + operationHistory.getOperationDefinition().getDisplayName() + " on " + storageNode.getResource() + + ": " + operationHistory.getErrorMessage()); + newStorageNode.setErrorMessage("Deployment has been aborted due to canceled resource operation on " + storageNode.getAddress()); storageNode.setErrorMessage("Deployment of " + newStorageNode.getAddress() + " has been aborted due " + @@ -307,6 +328,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
private void operationCanceled(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { + log.error("Deployment has been aborted due to canceled operation [" + + operationHistory.getOperationDefinition().getDisplayName() + " on " + newStorageNode.getResource() + + ": " + operationHistory.getErrorMessage()); + newStorageNode.setErrorMessage("Deployment has been aborted due to canceled resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); newStorageNode.setFailedOperation(operationHistory); @@ -314,6 +339,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
private void operationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, StorageNode newStorageNode) { + log.error("Deployment has been aborted due to failed operation [" + + operationHistory.getOperationDefinition().getDisplayName() + "] on " + storageNode.getResource() + + ": " + operationHistory.getErrorMessage()); + newStorageNode.setErrorMessage("Deployment has been aborted due to failed resource operation on " + storageNode.getAddress()); storageNode.setErrorMessage("Deployment of " + newStorageNode.getAddress() + " has been aborted due " + @@ -322,6 +351,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
private void operationFailed(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { + log.error("Deployment has been aborted due to failed operation [" + + operationHistory.getOperationDefinition().getDisplayName() + "] on " + newStorageNode.getResource() + + ": " + operationHistory.getErrorMessage()); + newStorageNode.setErrorMessage("Deployment has been aborted due to failed resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); newStorageNode.setFailedOperation(operationHistory); @@ -391,28 +424,21 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa }
private StorageNode findStorageNodeByAddress(String address) { - try { - return entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, StorageNode.class) + return entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, StorageNode.class) .setParameter("address", address).getSingleResult(); - - } catch (PersistenceException e) { - throw new StorageNodeDeploymentException("Storage node deployment has failed! Failed to fetch the next " + - "storage node at " + address + " to be updated.", e); - } }
private StorageNode findNewStorgeNode(StorageNode.OperationMode operationMode) { - try { - return entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class) + return entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class) .setParameter("operationMode", operationMode).getSingleResult(); - } catch (PersistenceException e) { - throw new StorageNodeDeploymentException("Storage node deployment has failed! Failed to fetch the " + - "storage node to be deployed.", e); - } }
- private boolean isStorageNodeOperation(OperationDefinition operationDefinition) { - ResourceType resourceType = operationDefinition.getResourceType(); + private boolean isStorageNodeOperation(ResourceOperationHistory operationHistory) { + if (operationHistory == null) { + return false; + } + + ResourceType resourceType = operationHistory.getOperationDefinition().getResourceType(); return resourceType.getName().equals(STORAGE_NODE_TYPE_NAME) && resourceType.getPlugin().equals(STORAGE_NODE_PLUGIN_NAME); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java index 44bb842..83b0ce5 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java @@ -7,6 +7,7 @@ import javax.ejb.Asynchronous; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.operation.OperationHistory; +import org.rhq.core.domain.operation.ResourceOperationHistory;
/** * @author John Sanda @@ -16,6 +17,12 @@ public interface StorageNodeOperationsHandlerLocal { @Asynchronous void handleOperationUpdateIfNecessary(OperationHistory operationHistory);
+ void handleUpdateKnownNodes(ResourceOperationHistory operationHistory); + + void handlePrepareForBootstrap(ResourceOperationHistory operationHistory); + + void handleAddNodeMaintenance(ResourceOperationHistory operationHistory); + void announceStorageNode(Subject subject, StorageNode storageNode);
void bootstrapStorageNode(Subject subject, StorageNode storageNode); @@ -23,4 +30,6 @@ public interface StorageNodeOperationsHandlerLocal { void performAddNodeMaintenanceIfNecessary(InetAddress storageNodeAddress);
void performAddNodeMaintenance(Subject subject, StorageNode storageNode); + + void logError(StorageNode.OperationMode newStorageNodeOperationMode, String error, Exception e); }
commit c354d1e1dc47f65cc44cd89305dcbb8e714b0e64 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 17:36:23 2013 -0400
capture and log deployment failures that result from failed resource operations
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 34f6381..861e3fa 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -182,7 +182,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN if (log.isInfoEnabled()) { log.info("Scheduling cluster maintenance to deploy " + storageNode + " into the storage cluster..."); } - deployStorageNode(subjectManager.getOverlord(), storageNode.getId()); + deployStorageNode(subjectManager.getOverlord(), storageNode); } } catch (UnknownHostException e) { throw new RuntimeException("Could not resolve address [" + address + "]. The resource " + resource + @@ -233,18 +233,21 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN }
@Override - public void deployStorageNode(Subject subject, int storageNodeId) { - StorageNode storageNode = entityManager.find(StorageNode.class, storageNodeId); + public void deployStorageNode(Subject subject, StorageNode storageNode) { + storageNode = entityManager.find(StorageNode.class, storageNode.getId());
switch (storageNode.getOperationMode()) { case INSTALLED: case ANNOUNCE: + reset(); storageNodeOperationsHandler.announceStorageNode(subject, storageNode); break; case BOOTSTRAP: + reset(); storageNodeOperationsHandler.bootstrapStorageNode(subject, storageNode); break; case ADD_NODE_MAINTENANCE: + reset(); storageNodeOperationsHandler.performAddNodeMaintenance(subject, storageNode); default: // For any other operation mode, the storage node should already be part of @@ -253,6 +256,13 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN } }
+ private void reset() { + for (StorageNode storageNode : getStorageNodes()) { + storageNode.setErrorMessage(null); + storageNode.setFailedOperation(null); + } + } + private List<StorageNode> combine(List<StorageNode> storageNodes, StorageNode storageNode) { List<StorageNode> newList = new ArrayList<StorageNode>(storageNodes.size() + 1); newList.addAll(storageNodes); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java index e5f4f22..75a795c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java @@ -169,5 +169,5 @@ public interface StorageNodeManagerLocal {
StorageNode createStorageNode(Resource resource);
- void deployStorageNode(Subject subject, int storageNodeId); + void deployStorageNode(Subject subject, StorageNode storageNode); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java index 75ac02b..2255299 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java @@ -96,4 +96,6 @@ public interface StorageNodeManagerRemote { * @return all storage nodes alerts */ PageList<Alert> findAllStorageNodeAlerts(Subject subject, StorageNode storageNode); + + void deployStorageNode(Subject sbubject, StorageNode storageNode); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index f996bf2..aaa54f5 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -2,10 +2,8 @@ package org.rhq.enterprise.server.storage;
import java.net.InetAddress; import java.util.ArrayList; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Set;
import javax.ejb.Asynchronous; import javax.ejb.EJB; @@ -23,7 +21,6 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.configuration.Configuration; -import org.rhq.core.domain.configuration.Property; import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.operation.OperationDefinition; @@ -194,15 +191,20 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa // nothing to do here return; case CANCELED: + // TODO Verify whether or not the node has been bootstrapped + // If the operation is canceled the plugin will get an InterruptedException. + // The actual bootstrapping may very well complete so we need to add in some + // checks to find out if the node is up and part of the cluster. + log.error("The operation [prepareForBootstrap] was canceled for " + newStorageNode + ". Deployment of the new storage node cannot proceed."); - // TODO update workflow status (the status needs to be accessible in the UI) + operationCanceled(newStorageNode, resourceOperationHistory); return; case FAILURE: log.error("The operation [preparedForBootstrap] failed for " + newStorageNode + ". The reported " + "failure is: " + resourceOperationHistory.getErrorMessage()); log.error("Deployment of the new storage node cannot proceed."); - // TODO update workflow status (the status needs to be accessible in the UI) + operationFailed(newStorageNode, resourceOperationHistory); return; default: // SUCCESS // Nothing to do because we wait for the C* driver to notify us that the @@ -212,6 +214,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
private void handleUpdateKnownNodes(ResourceOperationHistory resourceOperationHistory) { StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); + StorageNode newStorageNode = null; switch (resourceOperationHistory.getStatus()) { case INPROGRESS: // nothing to do here @@ -219,13 +222,14 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa case CANCELED: log.error("The operation [updateKnownNodes] was canceled for " + storageNode + ". Deployment of the new storage node cannot proceed."); - // TODO update workflow status (the status needs to be accessible in the UI) - return; + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + operationCanceled(storageNode, resourceOperationHistory, newStorageNode); case FAILURE: log.error("The operation [updateKnownNodes] failed for " + storageNode + ". The reported " + "failure is: " + resourceOperationHistory.getErrorMessage()); log.error("Deployment of the new storage node cannot proceed."); - // TODO update workflow status (the status needs to be accessible in the UI) + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + operationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS if (log.isInfoEnabled()) { @@ -235,7 +239,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa PropertyList addresses = parameters.getList("addresses"); List<String> remainingNodes = getRemainingNodes(resourceOperationHistory);
- StorageNode newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); Subject subject = getSubject(resourceOperationHistory);
if (remainingNodes.isEmpty()) { @@ -248,13 +252,9 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } }
- private Subject getSubject(ResourceOperationHistory resourceOperationHistory) { - Subject subject = subjectManager.getSubjectByName(resourceOperationHistory.getSubjectName()); - return SessionManager.getInstance().put(subject); - } - private void handleAddNodeMaintenance(ResourceOperationHistory resourceOperationHistory) { StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); + StorageNode newStorageNode = null; switch (resourceOperationHistory.getStatus()) { case INPROGRESS: // nothing to do here @@ -262,13 +262,15 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa case CANCELED: log.error("The operation [addNodeMaintenance] was canceled for " + storageNode + ". This operation " + "needs to be run on each storage node when a new node is added to the cluster."); - // TODO update workflow status (the status needs to be accessible in the UI) + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + operationCanceled(storageNode, resourceOperationHistory, newStorageNode); return; case FAILURE: log.error("The operation [addNodeMaintenance] failed for " + storageNode + ". This operation " + "needs to be run on each storage node when a new node is added to the cluster. The reported " + "failure is: " + resourceOperationHistory.getErrorMessage()); - // TODO update workflow status (the status needs to be accessible in the UI) + newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + operationFailed(storageNode, resourceOperationHistory, newStorageNode); return; default: // SUCCESS if (log.isInfoEnabled()) { @@ -289,6 +291,42 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa } }
+ private Subject getSubject(ResourceOperationHistory resourceOperationHistory) { + Subject subject = subjectManager.getSubjectByName(resourceOperationHistory.getSubjectName()); + return SessionManager.getInstance().put(subject); + } + + private void operationCanceled(StorageNode storageNode, ResourceOperationHistory operationHistory, + StorageNode newStorageNode) { + newStorageNode.setErrorMessage("Deployment has been aborted due to canceled resource operation on " + + storageNode.getAddress()); + storageNode.setErrorMessage("Deployment of " + newStorageNode.getAddress() + " has been aborted due " + + "to cancellation of resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + + "]."); + storageNode.setFailedOperation(operationHistory); + } + + private void operationCanceled(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { + newStorageNode.setErrorMessage("Deployment has been aborted due to canceled resource operation [" + + operationHistory.getOperationDefinition().getDisplayName() + "]."); + newStorageNode.setFailedOperation(operationHistory); + } + + private void operationFailed(StorageNode storageNode, ResourceOperationHistory operationHistory, + StorageNode newStorageNode) { + newStorageNode.setErrorMessage("Deployment has been aborted due to failed resource operation on " + + storageNode.getAddress()); + storageNode.setErrorMessage("Deployment of " + newStorageNode.getAddress() + " has been aborted due " + + "to failed resource operation [" + operationHistory.getOperationDefinition().getDisplayName() + "]."); + storageNode.setFailedOperation(operationHistory); + } + + private void operationFailed(StorageNode newStorageNode, ResourceOperationHistory operationHistory) { + newStorageNode.setErrorMessage("Deployment has been aborted due to failed resource operation [" + + operationHistory.getOperationDefinition().getDisplayName() + "]."); + newStorageNode.setFailedOperation(operationHistory); + } + private StorageNode findStorageNode(Resource resource) { for (StorageNode storageNode : storageNodeManager.getStorageNodes()) { if (storageNode.getResource().getId() == resource.getId()) { @@ -298,31 +336,6 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return null; }
- private StorageNode findStorageNodeToPrepareForBootstrap(PropertyList addressList) { - // It is possible that we could have more that one INSTALLED node. We want to make - // sure we grab the one that was just announced to the cluster. - Set<String> addresses = toSet(addressList); - List<StorageNode> installedNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, - StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.INSTALLED).getResultList(); - - for (StorageNode installedNode : installedNodes) { - if (addresses.contains(installedNode.getAddress())) { - return installedNode; - } - } - // TODO What should we do in the very unlikely event that we do not find the IP address? - throw new IllegalStateException("Failed to find storage node to be bootstrapped."); - } - - private Set<String> toSet(PropertyList propertyList) { - Set<String> set = new HashSet<String>(); - for (Property property : propertyList.getList()) { - PropertySimple simple = (PropertySimple) property; - set.add(simple.getStringValue()); - } - return set; - } - @Override public void bootstrapStorageNode(Subject subject, StorageNode storageNode) { List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE,
commit 84c256669df2632a7db803e551c35969605dab41 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 16:13:18 2013 -0400
add fields in StorageNode for error reporting during maintenance
Storage node deployment and undeployment consists of a series of different resource operations. The (un)deployment work flow could fail due to one of those resource operations. When that occurs we can provide a direct link in the StorageNode.failedOperation field to the operation history of the failed operation. This direct link will help with providing quick insight into the cause of the failure.
There is also a new errorMessage field in StorageNode. This field will provide summary info about the failure. If the failure is in server side processing and not in a resource operation, then the errorMessage field should be set but not the failedOperation field.
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml index c15aa1f..f307ff8 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/measurement-schema.xml @@ -454,7 +454,9 @@ <column name="OPERATION_MODE" required="true" size="32" type="VARCHAR2" /> <column name="CTIME" required="true" type="LONG" /> <column name="MTIME" required="true" type="LONG" /> - <column name="RESOURCE_ID" required="false" type="INTEGER" references="RHQ_RESOURCE(ID)" /> + <column name="ERROR_MSG" required="false" type="LONGVARCHAR"/> + <column name="RESOURCE_ID" required="false" type="INTEGER" references="RHQ_RESOURCE(ID)" /> + <column name="RESOURCE_OP_HIST_ID" required="false" type="INTEGER" references="RHQ_OPERATION_HISTORY(ID)"/>
<!-- This index is for constraint, not performance --> <index name="RHQ_STORAGE_NODE_UNIQUE" unique="true"> diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 6f42345..edf0147 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2184,6 +2184,19 @@ <schema-alterColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" nullable="false" default="unlimited"/> </schemaSpec>
+ <schemaSpec version="2.137"> + <schema-addColumn table="RHQ_STORAGE_NODE" column="ERROR_MSG" columnType="LONGVARCHAR"/> + <schema-addColumn table="RHQ_STORAGE_NODE" column="RESOURCE_OP_HIST_ID" columnType="INTEGER"/> + <schema-directSQL> + <statement desc="Creating RHQ_STORAGE_NODE foreign key to RHQ_OPERATION_HISTORY"> + ALTER TABLE RHQ_STORAGE_NODE + ADD CONSTRAINT RHQ_SN_OP_HIST_ID_FK + FOREIGN KEY (RESOURCE_OP_HIST_ID) + REFERENCES RHQ_OPERATION_HISTORY (ID) + </statement> + </schema-directSQL> + </schemaSpec> + </dbupgrade> </target> </project> diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index 3e94526..3f2a89c 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -40,6 +40,7 @@ import javax.persistence.PrePersist; import javax.persistence.SequenceGenerator; import javax.persistence.Table;
+import org.rhq.core.domain.operation.ResourceOperationHistory; import org.rhq.core.domain.resource.Resource;
/** @@ -134,10 +135,17 @@ public class StorageNode implements Serializable { @Column(name = "MTIME", nullable = false) private long mtime;
+ @Column(name = "ERROR_MSG", nullable = true) + private String errorMessage; + @JoinColumn(name = "RESOURCE_ID", referencedColumnName = "ID", nullable = true) @OneToOne(fetch = FetchType.EAGER, optional = true) private Resource resource;
+ @JoinColumn(name = "RESOURCE_OP_HIST_ID", referencedColumnName = "ID", nullable = true) + @OneToOne(optional = true) + private ResourceOperationHistory failedOperation; + // required for JPA public StorageNode() { } @@ -198,6 +206,22 @@ public class StorageNode implements Serializable { this.resource = resource; }
+ public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public ResourceOperationHistory getFailedOperation() { + return failedOperation; + } + + public void setFailedOperation(ResourceOperationHistory failedOperation) { + this.failedOperation = failedOperation; + } + public OperationMode getOperationMode() { return operationMode; }
commit bc812c9f6b4371a48d8268e292ad1020fee94725 Author: John Sanda jsanda@redhat.com Date: Wed Aug 14 12:08:13 2013 -0400
refactoring state transitions and adding method for deployment
When a storage node is committed into inventory its operation mode is set to INSTALLED, unless the storage node entity exists in which case the mode is set to NORMAL. After creating the storage node entity, deployment is started. The operation mode changs to ANNOUNCE. The address of the new node is announced to existing cluster nodes. After announcing completes, the operation mode changes to BOOTSTRAP, and the prepareForBootstrap operation is run on the new node. When the new node is reported up as part of the cluster, the operation mode of all cluster modes is set to ADD_NODE_MAINTENANCE. The addNodeMaintenance operation is then run on each storage node. When that operation completes, the node's operation mode is set back to NORMAL.
The StorageNodeManagerBean.deployStorageNode method looks at the operation mode of the node to determine at what step in the process to start the deployment. The deployStorageNode method is the only method that the UI or remote API will need to invoke to start or resume a deployment.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java index 6a5cf6a..3e94526 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNode.java @@ -209,11 +209,13 @@ public class StorageNode implements Serializable { public enum OperationMode {
DOWN("This storage node is down"), // - INSTALLED("This storage node is newly installed but not yet operationial"), // + INSTALLED("This storage node is newly installed but not yet operational"), // MAINTENANCE("This storage node is in maintenance mode"), // NORMAL("This storage node is running normally"), - ANNOUNCE("The storage node is running normally and is being updated to have newly deployed storage nodes " + - "announced to it so that those new nodes can join the cluster."), + ANNOUNCE("The storage node is installed but not yet part of the cluster. It is being announced so that it " + + "can join the cluster."), + BOOTSTRAP("The storage is installed but not yet part of the cluster. It is getting bootstrapped into the " + + "cluster"), ADD_NODE_MAINTENANCE("The storage node is running and is preparing to undergo routine maintenance that is " + "necessary when a new node joins the cluster.");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 11d81b4..34f6381 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -177,21 +177,12 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN storageNode.setOperationMode(OperationMode.NORMAL); initClusterSettingsIfNecessary(pluginConfig); } else { - storageNode = new StorageNode(); - storageNode.setAddress(address); - storageNode.setCqlPort(Integer.parseInt(pluginConfig.getSimpleValue(RHQ_STORAGE_CQL_PORT_PROPERTY))); - storageNode.setJmxPort(Integer.parseInt(pluginConfig.getSimpleValue(RHQ_STORAGE_JMX_PORT_PROPERTY))); - storageNode.setResource(resource); - storageNode.setOperationMode(OperationMode.INSTALLED); - - entityManager.persist(storageNode); + storageNode = createStorageNode(resource);
if (log.isInfoEnabled()) { - log.info(storageNode + " is a new storage node and not part of the storage node cluster."); - log.info("Scheduling maintenance operations to bring " + storageNode + " into the cluster..."); + log.info("Scheduling cluster maintenance to deploy " + storageNode + " into the storage cluster..."); } - - announceNewNode(storageNode); + deployStorageNode(subjectManager.getOverlord(), storageNode.getId()); } } catch (UnknownHostException e) { throw new RuntimeException("Could not resolve address [" + address + "]. The resource " + resource + @@ -224,17 +215,42 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN storageClusterSettingsManager.setClusterSettings(subjectManager.getOverlord(), clusterSettings); }
- private void announceNewNode(StorageNode newStorageNode) { - if (log.isInfoEnabled()) { - log.info("Announcing " + newStorageNode + " to storage node cluster."); - } + @Override + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public StorageNode createStorageNode(Resource resource) { + Configuration pluginConfig = resource.getPluginConfiguration(); + + StorageNode storageNode = new StorageNode(); + storageNode.setAddress(pluginConfig.getSimpleValue(RHQ_STORAGE_ADDRESS_PROPERTY)); + storageNode.setCqlPort(Integer.parseInt(pluginConfig.getSimpleValue(RHQ_STORAGE_CQL_PORT_PROPERTY))); + storageNode.setJmxPort(Integer.parseInt(pluginConfig.getSimpleValue(RHQ_STORAGE_JMX_PORT_PROPERTY))); + storageNode.setResource(resource); + storageNode.setOperationMode(OperationMode.INSTALLED);
- List<StorageNode> clusteredNodes = getClusteredStorageNodes(); - for (StorageNode node : clusteredNodes) { - node.setOperationMode(OperationMode.ANNOUNCE); + entityManager.persist(storageNode); + + return storageNode; + } + + @Override + public void deployStorageNode(Subject subject, int storageNodeId) { + StorageNode storageNode = entityManager.find(StorageNode.class, storageNodeId); + + switch (storageNode.getOperationMode()) { + case INSTALLED: + case ANNOUNCE: + storageNodeOperationsHandler.announceStorageNode(subject, storageNode); + break; + case BOOTSTRAP: + storageNodeOperationsHandler.bootstrapStorageNode(subject, storageNode); + break; + case ADD_NODE_MAINTENANCE: + storageNodeOperationsHandler.performAddNodeMaintenance(subject, storageNode); + default: + // For any other operation mode, the storage node should already be part of + // the cluster. + // TODO Make sure that the storage node is in fact part of the cluster } - PropertyList addresses = createPropertyListOfAddresses("addresses", combine(clusteredNodes, newStorageNode)); - storageNodeOperationsHandler.announceNewStorageNode(newStorageNode, clusteredNodes.get(0), addresses); }
private List<StorageNode> combine(List<StorageNode> storageNodes, StorageNode storageNode) { @@ -254,12 +270,6 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN }
@Override - public boolean isAddNodeMaintenanceInProgress() { - return !entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE) - .setParameter("operationMode", OperationMode.ADD_NODE_MAINTENANCE).getResultList().isEmpty(); - } - - @Override @RequiredPermission(Permission.MANAGE_SETTINGS) public StorageNodeLoadComposite getLoad(Subject subject, StorageNode node, long beginTime, long endTime) { int resourceId = getResourceIdFromStorageNode(node); @@ -418,11 +428,6 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN return result; }
- private List<StorageNode> getClusteredStorageNodes() { - return entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class) - .setParameter("operationMode", OperationMode.NORMAL).getResultList(); - } - @Override @RequiredPermission(Permission.MANAGE_SETTINGS) public PageList<StorageNode> findStorageNodesByCriteria(Subject subject, StorageNodeCriteria criteria) { @@ -796,4 +801,4 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN return successResultFound; }
-} \ No newline at end of file +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java index b5ee7f0..e5f4f22 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java @@ -167,5 +167,7 @@ public interface StorageNodeManagerLocal {
Map<String, List<MeasurementDataNumericHighLowComposite>> findStorageNodeLoadDataForLast(Subject subject, StorageNode node, long beginTime, long endTime, int numPoints);
- boolean isAddNodeMaintenanceInProgress(); + StorageNode createStorageNode(Resource resource); + + void deployStorageNode(Subject subject, int storageNodeId); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java index 734da35..7db95fb 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterMonitor.java @@ -7,7 +7,6 @@ import com.datastax.driver.core.exceptions.NoHostAvailableException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
-import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal; import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.server.metrics.StorageStateListener;
@@ -30,12 +29,8 @@ public class StorageClusterMonitor implements StorageStateListener {
isClusterAvailable = true;
- StorageNodeManagerLocal storageNodeManager = LookupUtil.getStorageNodeManager(); - if (storageNodeManager.isAddNodeMaintenanceInProgress()) { - log.info("Scheduling cluster maintenance..."); - StorageNodeOperationsHandlerLocal storageOperationsHandler = LookupUtil.getStorageNodeOperationsHandler(); - storageOperationsHandler.performAddNodeMaintenance(address); - } + StorageNodeOperationsHandlerLocal storageOperationsHandler = LookupUtil.getStorageNodeOperationsHandler(); + storageOperationsHandler.performAddNodeMaintenanceIfNecessary(address); }
@Override diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java new file mode 100644 index 0000000..fca6e96 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeDeploymentException.java @@ -0,0 +1,22 @@ +package org.rhq.enterprise.server.storage; + +/** + * @author John Sanda + */ +public class StorageNodeDeploymentException extends RuntimeException { + + public StorageNodeDeploymentException() { + } + + public StorageNodeDeploymentException(String message) { + super(message); + } + + public StorageNodeDeploymentException(String message, Throwable cause) { + super(message, cause); + } + + public StorageNodeDeploymentException(Throwable cause) { + super(cause); + } +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index 1bf3cec..f996bf2 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -1,15 +1,20 @@ package org.rhq.enterprise.server.storage;
import java.net.InetAddress; +import java.util.ArrayList; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Set;
import javax.ejb.Asynchronous; import javax.ejb.EJB; import javax.ejb.Stateless; +import javax.ejb.TransactionAttribute; +import javax.ejb.TransactionAttributeType; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,6 +34,7 @@ import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.util.StringUtil; import org.rhq.enterprise.server.RHQConstants; +import org.rhq.enterprise.server.auth.SessionManager; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.cloud.StorageNodeManagerLocal; import org.rhq.enterprise.server.operation.OperationManagerLocal; @@ -69,39 +75,72 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa private StorageClientManagerBean storageClientManager;
@Override - public void announceNewStorageNode(StorageNode newStorageNode, StorageNode clusterNode, PropertyList addresses) { + @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) + public void announceStorageNode(Subject subject, StorageNode storageNode) { if (log.isInfoEnabled()) { - log.info("Announcing new storage node " + newStorageNode + " to cluster node " + clusterNode); + log.info("Announcing " + storageNode + " to storage node cluster."); + } + storageNode.setOperationMode(StorageNode.OperationMode.ANNOUNCE); + List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); + List<StorageNode> allNodes = new ArrayList<StorageNode>(clusterNodes); + allNodes.add(storageNode); + + announceStorageNode(subject, storageNode, createPropertyListOfAddresses("addresses", allNodes), + getAddresses(clusterNodes)); + + } + + private void announceStorageNode(Subject subject, StorageNode storageNode, PropertyList addresses, + List<String> remainingNodes) { + String address = remainingNodes.remove(0); + StorageNode clusterNode = findStorageNodeByAddress(address); + + if (log.isInfoEnabled()) { + log.info("Announcing " + storageNode + " to cluster node " + clusterNode); } - Subject overlord = subjectManager.getOverlord(); ResourceOperationSchedule schedule = new ResourceOperationSchedule(); schedule.setResource(clusterNode.getResource()); schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(overlord); + schedule.setSubject(subject); schedule.setOperationName("updateKnownNodes"); Configuration parameters = new Configuration(); parameters.put(addresses); + parameters.put(new PropertySimple("remainingNodes", StringUtil.listToString(remainingNodes))); schedule.setParameters(parameters);
- operationManager.scheduleResourceOperation(overlord, schedule); + operationManager.scheduleResourceOperation(subject, schedule); }
@Override - public void performAddNodeMaintenance(InetAddress storageNodeAddress) { + public void performAddNodeMaintenanceIfNecessary(InetAddress storageNodeAddress) { StorageNode storageNode = entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, StorageNode.class).setParameter("address", storageNodeAddress.getHostAddress()).getSingleResult(); - storageNode.setOperationMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE);
+ if (storageNode.getOperationMode() == StorageNode.OperationMode.BOOTSTRAP) { + performAddNodeMaintenance(subjectManager.getOverlord(), storageNode); + } else { + log.info(storageNode + " has already been bootstrapped. Skipping add node maintenance."); + } + } + + @Override + public void performAddNodeMaintenance(Subject subject, StorageNode storageNode) { + storageNode.setOperationMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, - StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.ADD_NODE_MAINTENANCE) + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL) .getResultList(); - + for (StorageNode node : clusterNodes) { + node.setOperationMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); + } + clusterNodes.add(storageNode); boolean runRepair = updateSchemaIfNecessary(clusterNodes); - - performAddNodeMaintenance(storageNode, runRepair, createPropertyListOfAddresses(SEEDS_LIST, clusterNodes)); + performAddNodeMaintenance(subject, storageNode, runRepair, createPropertyListOfAddresses(SEEDS_LIST, + clusterNodes)); }
- private void performAddNodeMaintenance(StorageNode storageNode, boolean runRepair, PropertyList seedsList) { + private void performAddNodeMaintenance(Subject subject, StorageNode storageNode, boolean runRepair, + PropertyList seedsList) { if (log.isInfoEnabled()) { log.info("Running addNodeMaintenance for storage node " + storageNode); } @@ -111,7 +150,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa ResourceOperationSchedule schedule = new ResourceOperationSchedule(); schedule.setResource(storageNode.getResource()); schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(overlord); + schedule.setSubject(subject); schedule.setOperationName("addNodeMaintenance");
Configuration config = new Configuration(); @@ -192,22 +231,28 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa if (log.isInfoEnabled()) { log.info("Finished announcing cluster nodes to " + storageNode); } - storageNode.setOperationMode(StorageNode.OperationMode.ADD_NODE_MAINTENANCE); Configuration parameters = resourceOperationHistory.getParameters(); PropertyList addresses = parameters.getList("addresses"); - StorageNode nextNode = takeFromQueue(storageNode, StorageNode.OperationMode.ANNOUNCE); + List<String> remainingNodes = getRemainingNodes(resourceOperationHistory);
- if (nextNode == null) { + StorageNode newStorageNode = findNewStorgeNode(StorageNode.OperationMode.ANNOUNCE); + Subject subject = getSubject(resourceOperationHistory); + + if (remainingNodes.isEmpty()) { log.info("Successfully announced new storage node to cluster"); - StorageNode installedNode = findStorageNodeToPrepareForBootstrap(addresses); - // Pass a copy of addresses to avoid a TransientObjectException - prepareNodeForBootstrap(installedNode, addresses.deepCopy(false)); + newStorageNode.setOperationMode(StorageNode.OperationMode.BOOTSTRAP); + prepareNodeForBootstrap(subject, newStorageNode, addresses.deepCopy(false)); } else { - announceNewStorageNode(storageNode, nextNode, addresses.deepCopy(false)); + announceStorageNode(subject, newStorageNode, addresses.deepCopy(false), remainingNodes); } } }
+ private Subject getSubject(ResourceOperationHistory resourceOperationHistory) { + Subject subject = subjectManager.getSubjectByName(resourceOperationHistory.getSubjectName()); + return SessionManager.getInstance().put(subject); + } + private void handleAddNodeMaintenance(ResourceOperationHistory resourceOperationHistory) { StorageNode storageNode = findStorageNode(resourceOperationHistory.getResource()); switch (resourceOperationHistory.getStatus()) { @@ -238,7 +283,8 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa Configuration parameters = resourceOperationHistory.getParameters(); boolean runRepair = parameters.getSimple(RUN_REPAIR_PROPERTY).getBooleanValue(); PropertyList seedsList = parameters.getList(SEEDS_LIST).deepCopy(false); - performAddNodeMaintenance(nextNode, runRepair, seedsList); + Subject subject = getSubject(resourceOperationHistory); + performAddNodeMaintenance(subject, nextNode, runRepair, seedsList); } } } @@ -277,7 +323,15 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return set; }
- private void prepareNodeForBootstrap(StorageNode storageNode, PropertyList addresses) { + @Override + public void bootstrapStorageNode(Subject subject, StorageNode storageNode) { + List<StorageNode> clusterNodes = entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, + StorageNode.class).setParameter("operationMode", StorageNode.OperationMode.NORMAL).getResultList(); + clusterNodes.add(storageNode); + prepareNodeForBootstrap(subject, storageNode, createPropertyListOfAddresses("addresses", clusterNodes)); + } + + private void prepareNodeForBootstrap(Subject subject, StorageNode storageNode, PropertyList addresses) { if (log.isInfoEnabled()) { log.info("Preparing to bootstrap " + storageNode + " into cluster..."); } @@ -285,11 +339,10 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa ResourceOperationSchedule schedule = new ResourceOperationSchedule(); schedule.setResource(storageNode.getResource()); schedule.setJobTrigger(JobTrigger.createNowTrigger()); - schedule.setSubject(subjectManager.getOverlord()); + schedule.setSubject(subject); schedule.setOperationName("prepareForBootstrap");
- StorageClusterSettings clusterSettings = storageClusterSettingsManager.getClusterSettings( - subjectManager.getOverlord()); + StorageClusterSettings clusterSettings = storageClusterSettingsManager.getClusterSettings(subject); Configuration parameters = new Configuration(); parameters.put(new PropertySimple("cqlPort", clusterSettings.getCqlPort())); parameters.put(new PropertySimple("gossipPort", clusterSettings.getGossipPort())); @@ -297,7 +350,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa
schedule.setParameters(parameters);
- operationManager.scheduleResourceOperation(subjectManager.getOverlord(), schedule); + operationManager.scheduleResourceOperation(subject, schedule); }
private StorageNode takeFromQueue(StorageNode lastTaken, StorageNode.OperationMode queue) { @@ -311,6 +364,40 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return nodes.get(0); }
+ private List<String> getRemainingNodes(ResourceOperationHistory resourceOperationHistory) { + LinkedList<String> addresses = new LinkedList<String>(); + Configuration results = resourceOperationHistory.getResults(); + String remainingNodes = results.getSimpleValue("remainingNodes"); + + if (!StringUtil.isEmpty(remainingNodes)) { + for (String address : remainingNodes.split(",")) { + addresses.add(address); + } + } + return addresses; + } + + private StorageNode findStorageNodeByAddress(String address) { + try { + return entityManager.createNamedQuery(StorageNode.QUERY_FIND_BY_ADDRESS, StorageNode.class) + .setParameter("address", address).getSingleResult(); + + } catch (PersistenceException e) { + throw new StorageNodeDeploymentException("Storage node deployment has failed! Failed to fetch the next " + + "storage node at " + address + " to be updated.", e); + } + } + + private StorageNode findNewStorgeNode(StorageNode.OperationMode operationMode) { + try { + return entityManager.createNamedQuery(StorageNode.QUERY_FIND_ALL_BY_MODE, StorageNode.class) + .setParameter("operationMode", operationMode).getSingleResult(); + } catch (PersistenceException e) { + throw new StorageNodeDeploymentException("Storage node deployment has failed! Failed to fetch the " + + "storage node to be deployed.", e); + } + } + private boolean isStorageNodeOperation(OperationDefinition operationDefinition) { ResourceType resourceType = operationDefinition.getResourceType(); return resourceType.getName().equals(STORAGE_NODE_TYPE_NAME) && @@ -411,4 +498,12 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa return list; }
+ private List<String> getAddresses(List<StorageNode> storageNodes) { + List<String> addresses = new LinkedList<String>(); + for (StorageNode storageNode : storageNodes) { + addresses.add(storageNode.getAddress()); + } + return addresses; + } + } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java index fcdcd3e..44bb842 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerLocal.java @@ -4,8 +4,8 @@ import java.net.InetAddress;
import javax.ejb.Asynchronous;
+import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; -import org.rhq.core.domain.configuration.PropertyList; import org.rhq.core.domain.operation.OperationHistory;
/** @@ -16,7 +16,11 @@ public interface StorageNodeOperationsHandlerLocal { @Asynchronous void handleOperationUpdateIfNecessary(OperationHistory operationHistory);
- void announceNewStorageNode(StorageNode newStorageNode, StorageNode clusterNode, PropertyList addresses); + void announceStorageNode(Subject subject, StorageNode storageNode);
- void performAddNodeMaintenance(InetAddress storageNodeAddress); + void bootstrapStorageNode(Subject subject, StorageNode storageNode); + + void performAddNodeMaintenanceIfNecessary(InetAddress storageNodeAddress); + + void performAddNodeMaintenance(Subject subject, StorageNode storageNode); } diff --git a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java index e76cfa0..7f58037 100644 --- a/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java +++ b/modules/plugins/rhq-storage/src/main/java/org/rhq/plugins/storage/StorageNodeComponent.java @@ -255,7 +255,9 @@ public class StorageNodeComponent extends CassandraNodeComponent implements Oper EmsOperation emsOperation = authBean.getOperation("reloadConfiguration"); emsOperation.invoke();
- result.setSimpleResult("Successfully updated the set of known nodes."); + Configuration complexResults = result.getComplexResults(); + complexResults.put(new PropertySimple("details", "Successfully updated the set of known nodes.")); + complexResults.put(params.get("remainingNodes").deepCopy(false));
return result; } catch (InternodeAuthConfUpdateException e) { diff --git a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml index a2d04d0..4ef10cd 100644 --- a/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/rhq-storage/src/main/resources/META-INF/rhq-plugin.xml @@ -102,7 +102,12 @@ <c:list-property name="addresses"> <c:simple-property name="address"/> </c:list-property> + <c:simple-property name="remainingNodes"/> </parameters> + <results> + <c:simple-property name="details"/> + <c:simple-property name="remainingNodes"/> + </results> </operation>
<operation name="prepareForBootstrap">
commit a445939c2ee4940c43af7accae173beef2487b7e Author: Stefan Negrea snegrea@redhat.com Date: Wed Aug 14 17:58:32 2013 -0500
Add alert template for maintenance operation failures for storage nodes.
diff --git a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java index f752d1d..5692bea 100644 --- a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java +++ b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java @@ -66,11 +66,14 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone private static final String TOTAL_DISK_USED_PERCENTAGE_METRIC_NAME = "Calculated.TotalDiskUsedPercentage"; private static final String FREE_DISK_TO_DATA_SIZE_RATIO_METRIC_NAME = "Calculated.FreeDiskToDataSizeRatio"; private static final String TAKE_SNAPSHOT_OPERATION_NAME = "takeSnapshot"; + private static final String[] MAINTENANCE_OPERATIONS = new String[] { "readRepair", "addNodeMaintenance", + "updateKnownNodes", "prepareForBootstrap", "prepareForUpgrade", "updateSeedsList", "updateConfiguration" };
static private final List<InjectedTemplate> injectedTemplates; static private final InjectedTemplate storageNodeHighHeapTemplate; static private final InjectedTemplate storageNodeHighDiskUsageTemplate; static private final InjectedTemplate storageNodeSnapshotFailureTemplate; + static private final InjectedTemplate storageNodeMaintenanceOperationsFailureTemplate;
static { storageNodeHighHeapTemplate = new InjectedTemplate( @@ -91,10 +94,18 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone "StorageNodeSnapshotFailureTemplate", // "An alert template to notify users when a snapshot operations fails for an RHQ Storage Node. When fired please see documentation for the proper corrective action.");
+ storageNodeMaintenanceOperationsFailureTemplate = new InjectedTemplate( + "RHQStorage", // + "RHQ Storage Node", // + "StorageNodeMaintenanceOperationsFailureTemplate", // + "An alert template to notify users when a maintenance operation fails for an RHQ Storage Node. When fired please see documentation for the proper corrective action."); + injectedTemplates = new ArrayList<InjectedTemplate>(); injectedTemplates.add(storageNodeHighHeapTemplate); injectedTemplates.add(storageNodeHighDiskUsageTemplate); injectedTemplates.add(storageNodeSnapshotFailureTemplate); + injectedTemplates.add(storageNodeMaintenanceOperationsFailureTemplate); + }
private ServerPluginContext context; @@ -239,6 +250,8 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone newAlertDefId = injectStorageNodeHighDiskUsageTemplate(resourceType); } else if (storageNodeSnapshotFailureTemplate.equals(injectedAlertDef)) { newAlertDefId = injectStorageNodeSnapshotFailureTemplate(resourceType); + } else if (storageNodeMaintenanceOperationsFailureTemplate.equals(injectedAlertDef)) { + newAlertDefId = injectStorageNodeMaintenanceOperationsFailureTemplate(resourceType); }
adc.addFilterId(newAlertDefId); @@ -398,6 +411,36 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone return newTemplateId; }
+ private int injectStorageNodeMaintenanceOperationsFailureTemplate(ResourceType resourceType) { + AlertTemplateManagerLocal alertTemplateManager = LookupUtil.getAlertTemplateManager(); + SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager(); + + AlertDefinition newTemplate = new AlertDefinition(); + newTemplate.setName(storageNodeMaintenanceOperationsFailureTemplate.getName()); + newTemplate.setResourceType(resourceType); + newTemplate.setPriority(AlertPriority.MEDIUM); + newTemplate.setConditionExpression(BooleanExpression.ANY); + newTemplate.setDescription(storageNodeMaintenanceOperationsFailureTemplate.getDescription()); + newTemplate.setRecoveryId(0); + newTemplate.setEnabled(true); + + for (String operation : MAINTENANCE_OPERATIONS) { + AlertCondition snapshotFailureCondition = new AlertCondition(); + snapshotFailureCondition.setCategory(AlertConditionCategory.CONTROL); + snapshotFailureCondition.setName(operation); + snapshotFailureCondition.setOption(OperationRequestStatus.FAILURE.name()); + newTemplate.addCondition(snapshotFailureCondition); + } + + AlertDampening dampener = new AlertDampening(AlertDampening.Category.NONE); + newTemplate.setAlertDampening(dampener); + + int newTemplateId = alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate, + resourceType.getId()); + + return newTemplateId; + } + private static class InjectedTemplate { static public final String FIELD_PLUGIN_NAME = "plugin"; static public final String FIELD_RESOURCE_TYPE_NAME = "type";
commit 0efe7d068e9c99a551d458e056f6d0dc02683f1d Author: Stefan Negrea snegrea@redhat.com Date: Wed Aug 14 15:44:07 2013 -0500
Fixing errors after rebase merge.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index aa6f78f..11d81b4 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -153,7 +153,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN private ResourceManagerLocal resourceManager;
@EJB - private StorageClusterSettingsManagerBean storageClusterSettingsManager; + private StorageClusterSettingsManagerLocal storageClusterSettingsManager;
@EJB private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler; @@ -625,7 +625,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
return configuration; } - + @Override @Asynchronous public void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) {
commit 6b4c48aa910b21f0e1b391b4122f4bcfddc16590 Author: Stefan Negrea snegrea@redhat.com Date: Wed Aug 14 15:30:37 2013 -0500
More text for the schema compatibility text.
diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java index ec54a0c..fe6ddf9 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java @@ -36,6 +36,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.cassandra.schema.exception.InstalledSchemaTooAdvancedException; import org.rhq.cassandra.schema.exception.InstalledSchemaTooOldException; +import org.rhq.cassandra.schema.exception.SchemaNotInstalledException; import org.rhq.core.domain.cloud.StorageNode;
/** @@ -258,6 +259,11 @@ class VersionManager extends AbstractManager { try { initClusterSession();
+ if (!this.schemaExists()) { + log.error("Storage cluster schema not installed. Please re-run the server installer to install the storage cluster schema properly."); + throw new SchemaNotInstalledException(); + } + int installedSchemaVersion = this.getInstalledSchemaVersion();
UpdateFolder folder = new UpdateFolder(Task.Update.getFolder()); @@ -280,7 +286,7 @@ class VersionManager extends AbstractManager { } finally { shutdownClusterConnection();
- log.info("Completed check for storage schema compatibility."); + log.info("Completed storage schema compatibility check."); } } } diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java index 2f83ef5..bf36b25 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java @@ -33,6 +33,7 @@ public class InstalledSchemaTooAdvancedException extends Exception {
public InstalledSchemaTooAdvancedException() { super( - "Storage schema is too advanced for the current installation. Schema revisions have been applied beyond the capability of the installation."); + "Storage schema is too advanced for the current installation. Schema revisions have been applied beyond the capability of the installation. " + + "Please install a newer version of the server that is compatibile with the storage schema version."); } } \ No newline at end of file diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java index 4da863b..db4bfbf 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java @@ -29,10 +29,12 @@ package org.rhq.cassandra.schema.exception; /** * @author Stefan Negrea */ +@SuppressWarnings("serial") public class InstalledSchemaTooOldException extends Exception {
public InstalledSchemaTooOldException() { super( - "Storage schema needs to be updated. The schema manager contains updates not yet applied to the storage cluster installation."); + "Storage schema is not properly updated. The schema manager contains updates not yet applied to the storage cluster installation." + + "Please re-run the server installer to update the current schema to the latest version."); } } \ No newline at end of file diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/SchemaNotInstalledException.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/SchemaNotInstalledException.java new file mode 100644 index 0000000..63e9013 --- /dev/null +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/SchemaNotInstalledException.java @@ -0,0 +1,38 @@ +/* + * + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, 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.cassandra.schema.exception; + + +/** + * @author Stefan Negrea + */ +@SuppressWarnings("serial") +public class SchemaNotInstalledException extends Exception { + + public SchemaNotInstalledException() { + super("Storage schema is not properly installed. Please re-run the server installer to install storage schema."); + } +} \ No newline at end of file
commit d532f0aabd0a2ffae237e7e66d08810cd1de3c34 Author: Stefan Negrea snegrea@redhat.com Date: Wed Aug 14 14:37:26 2013 -0500
[BZ 991598] Add basica node configuration validation to the composite class. It validates heap settings as well as port settings.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeConfigurationComposite.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeConfigurationComposite.java index d7d7b7d..fccae9b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeConfigurationComposite.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/StorageNodeConfigurationComposite.java @@ -115,6 +115,54 @@ public class StorageNodeConfigurationComposite implements Serializable { this.heapNewSize = heapNewSize; }
+ public boolean validate() { + //validate heap settings + boolean validHeap = false; + + String heapSize = getHeapSize() == null ? null : (getHeapSize().trim().length() == 0 ? null : getHeapSize() + .trim().toLowerCase()); + String heapNewSize = getHeapNewSize() == null ? null : (getHeapNewSize().trim().length() == 0 ? null + : getHeapNewSize().trim().toLowerCase()); + + if (heapSize == null && heapNewSize == null) { + validHeap = true; + } else if (heapSize != null && heapNewSize != null) { + try { + int heapSizeParsed = 0; + if (heapSize.contains("g")) { + heapSizeParsed = Integer.parseInt(heapSize.replace("g", "")) * 1024; + } else if (heapSize.contains("m")) { + heapSizeParsed = Integer.parseInt(heapSize.toLowerCase().replace("m", "")); + } else { + throw new IllegalArgumentException(); + } + + int heapNewSizeParsed = 0; + if (heapNewSize.contains("g")) { + heapNewSizeParsed = Integer.parseInt(heapNewSize.replace("g", "")) * 1024; + } else if (heapNewSize.contains("m")) { + heapNewSizeParsed = Integer.parseInt(heapNewSize.toLowerCase().replace("m", "")); + } else { + throw new IllegalArgumentException(); + } + + if (heapNewSizeParsed < heapSizeParsed) { + validHeap = true; + } + } catch (Exception e) { + //Nothing to do heap settings are not valid since parsing failed at some point + } + } + + //validate JMX Port + boolean validJMXPort = false; + if (this.getJmxPort() < 65535) { + validJMXPort = true; + } + + return validHeap && validJMXPort; + } + /* (non-Javadoc) * @see java.lang.Object#toString() */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index d7085da..aa6f78f 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -153,7 +153,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN private ResourceManagerLocal resourceManager;
@EJB - private StorageClusterSettingsManagerLocal storageClusterSettingsManager; + private StorageClusterSettingsManagerBean storageClusterSettingsManager;
@EJB private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler; @@ -575,7 +575,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
@Override public Integer[] findResourcesWithAlertDefinitions(StorageNode storageNode) { - List<StorageNode> initialStorageNodes = null; + List<StorageNode> initialStorageNodes = getStorageNodes(); if (storageNode == null) { initialStorageNodes = getStorageNodes(); } else { @@ -625,7 +625,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
return configuration; } - + @Override @Asynchronous public void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) {
commit 3b6abb9b91f67dd8a9181419dbaacc35dc4754a5 Author: Mike Thompson mithomps@redhat.com Date: Wed Aug 14 10:32:20 2013 -0700
Add GraphMarker interface to mark places in the code where graphs are (later) injected by d3 javascript code.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/GraphMarker.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/GraphMarker.java new file mode 100644 index 0000000..da88999 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/GraphMarker.java @@ -0,0 +1,32 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client; + +/** + * Defines the first step in the 2 step approach to creating graphs. + * <ol> + * <li>Step 1: Create the graph marker in the page.</li> + * <li>Step 2: Create and Attach a graph to graph marker via HasD3MetricJsniChart.drawJsniChart</li> + * </ol> + * + * @author Mike Thompson + */ +public interface GraphMarker { + String createGraphMarker(); +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java index 59d4c75..eb20d40 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java @@ -40,7 +40,7 @@ import org.rhq.enterprise.gui.coregui.client.util.MeasurementConverterClient; */ public class AvailabilityOverUnderGraphType implements AvailabilityGraphType {
- private static Messages MSG = CoreGUI.getMessages(); + private static final Messages MSG = CoreGUI.getMessages(); private List<Availability> availabilityList; private List<ResourceGroupAvailability> groupAvailabilityList; private Integer entityId; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilitySummaryPieGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilitySummaryPieGraphType.java index 72438fd6..2099bfc 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilitySummaryPieGraphType.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilitySummaryPieGraphType.java @@ -23,6 +23,7 @@ import java.util.List;
import com.smartgwt.client.widgets.HTMLFlow;
+import org.rhq.enterprise.gui.coregui.client.GraphMarker; import org.rhq.enterprise.gui.coregui.client.util.Log;
/** @@ -32,7 +33,7 @@ import org.rhq.enterprise.gui.coregui.client.util.Log; * * @author Mike Thompson */ -public class AvailabilitySummaryPieGraphType { +public class AvailabilitySummaryPieGraphType implements GraphMarker{
public static final int HEIGHT = 75; public static final int WIDTH = 75; @@ -42,7 +43,14 @@ public class AvailabilitySummaryPieGraphType { public AvailabilitySummaryPieGraphType() { }
- public HTMLFlow createGraphMarker() { + public HTMLFlow addGraphMarkerMember(){ + HTMLFlow graphFlow = new HTMLFlow(createGraphMarker()); + graphFlow.setWidth(WIDTH); + graphFlow.setHeight(HEIGHT); + return graphFlow; + + } + public String createGraphMarker() { Log.debug("drawGraph marker in AvailabilitySummaryPieGraph");
StringBuilder divAndSvgDefs = new StringBuilder(); @@ -50,10 +58,7 @@ public class AvailabilitySummaryPieGraphType { divAndSvgDefs.append("<svg xmlns="http://www.w3.org/2000/svg%5C" version="1.1" style="height:" + HEIGHT + "px;" ></svg>"); divAndSvgDefs.append("</div>"); - HTMLFlow graphFlow = new HTMLFlow(divAndSvgDefs.toString()); - graphFlow.setWidth(WIDTH); - graphFlow.setHeight(HEIGHT); - return graphFlow; + return divAndSvgDefs.toString(); }
public void setAvailabilityData(String upLabel, double upPercent, String downLabel, double downPercent, diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java index 4dad9b1..20eb39b 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/MetricD3Graph.java @@ -21,6 +21,7 @@ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail.monitori import com.google.gwt.user.client.Timer; import com.smartgwt.client.widgets.HTMLFlow;
+import org.rhq.enterprise.gui.coregui.client.GraphMarker; import org.rhq.enterprise.gui.coregui.client.inventory.common.AbstractD3GraphListView; import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.Refreshable; import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl; @@ -31,7 +32,7 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; * A D3 graph implementation for graphing Resource metrics. * Just the graph only. No avail graph no buttons just he graph. */ -public class MetricD3Graph<T extends AbstractD3GraphListView> extends EnhancedVLayout implements Refreshable { +public class MetricD3Graph<T extends AbstractD3GraphListView> extends EnhancedVLayout implements Refreshable,GraphMarker {
protected StackedBarMetricGraphImpl graph; private HTMLFlow graphDiv = null; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java index 6e3b590..2c3a4c7 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java @@ -24,6 +24,7 @@ import com.smartgwt.client.widgets.HTMLFlow;
import org.rhq.core.domain.measurement.Availability; import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability; +import org.rhq.enterprise.gui.coregui.client.GraphMarker; import org.rhq.enterprise.gui.coregui.client.inventory.common.graph.AvailabilityGraphType; import org.rhq.enterprise.gui.coregui.client.util.Log; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; @@ -34,7 +35,7 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; * * @author Mike Thompson */ -public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends EnhancedVLayout { +public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends EnhancedVLayout implements GraphMarker {
protected T availabilityGraphType;
@@ -49,14 +50,14 @@ public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends En protected void onDraw() { super.onDraw(); removeMembers(getMembers()); - createGraphMarker(); + addGraphMarkerComponent(); }
@Override public void parentResized() { super.parentResized(); removeMembers(getMembers()); - createGraphMarker(); + addGraphMarkerComponent(); drawJsniChart(); }
@@ -76,7 +77,7 @@ public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends En * */
- public void createGraphMarker() { + public String createGraphMarker() { Log.debug("drawGraph marker in AvailabilityD3Graph for: " + availabilityGraphType.getChartId());
StringBuilder divAndSvgDefs = new StringBuilder(); @@ -99,11 +100,14 @@ public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends En divAndSvgDefs.append("</div>"); divAndSvgDefs.append("</div>"); // end availTooltipDiv divAndSvgDefs.append("</div>"); - HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString()); + return divAndSvgDefs.toString(); + } + + public void addGraphMarkerComponent(){ + HTMLFlow graph = new HTMLFlow(createGraphMarker()); graph.setWidth100(); graph.setHeight(65); addMember(graph); - }
/** diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/ResourceMetricAvailabilityView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/ResourceMetricAvailabilityView.java index 5835f61..a058e4f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/ResourceMetricAvailabilityView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/table/ResourceMetricAvailabilityView.java @@ -140,7 +140,7 @@ public class ResourceMetricAvailabilityView extends EnhancedVLayout {
CanvasItem availPieChartItem = new CanvasItem(); availPieChartItem.setTitle(MSG.pie_chart_availability_summary_label()); - availPieChartItem.setCanvas(availabilitySummaryPieGraph.createGraphMarker()); + availPieChartItem.setCanvas(availabilitySummaryPieGraph.addGraphMarkerMember()); availPieChartItem.setRowSpan(3); availPieChartItem.setVAlign(VerticalAlignment.TOP); availPieChartItem.setTitleVAlign(VerticalAlignment.TOP);
commit 5efdfc48b0a49e04cc931c31e5daf65c961440be Author: jfclere jfclere@neo2.gva.redhat.com Date: Mon Apr 15 17:07:28 2013 +0200
[BZ 865460] Cannot add a Group to tomcat's UserDatabase
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java index 0a95069..ead4956 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java @@ -51,6 +51,7 @@ public class TomcatUserDatabaseComponent extends MBeanResourceComponent<TomcatSe if (TomcatGroupComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) { name = report.getResourceConfiguration().getSimple("groupname").getStringValue(); newRoles = report.getResourceConfiguration().getSimple(TomcatGroupComponent.CONFIG_ROLES); + report.getResourceConfiguration().remove(TomcatGroupComponent.CONFIG_ROLES); objectName = String.format("Users:type=Group,groupname="%s",database=UserDatabase", name); operation = "createGroup"; } else if (TomcatRoleComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) {
commit c755c18fcb71e49b7c608add0a73eda50b08d741 Author: jfclere jfclere@neo2.gva.redhat.com Date: Mon Apr 15 16:28:19 2013 +0200
[BZ 921194] Additional corrections by lfuka.
diff --git a/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml index 653736f..2fd8931 100644 --- a/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml @@ -734,7 +734,9 @@ <c:simple-property name="name" type="string" - readOnly="true" /> + readOnly="true" + default="Default Tomcat Connector name" + description="Connector name."/> <c:simple-property name="port" type="string" @@ -748,8 +750,8 @@ <c:simple-property name="connector" type="string" - description="Connector protocol connector. Note: Only available on Tomcat 7." - required="false" + description="Connector protocol connector." + default="Default connector" readOnly="true" /> <c:simple-property name="address"
commit c1124838bb80b36f00dec71f12ca031e0b050cc4 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:26:38 2013 +0200
[BZ 921261] WebModule is reported as DOWN or UNAVAILABLE ... from da0179ab26a0c3e3a50238e9997147864e5a759b
diff --git a/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml index 97f410a..653736f 100644 --- a/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml @@ -748,7 +748,8 @@ <c:simple-property name="connector" type="string" - description="Connector protocol connector." + description="Connector protocol connector. Note: Only available on Tomcat 7." + required="false" readOnly="true" /> <c:simple-property name="address"
commit 109da29dcf07652933d3e814bd439d4600cca781 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:22:52 2013 +0200
[BZ 921261] WebModule is reported as DOWN or UNAVAILABLE ... from 00e594847fe67da46f8976df58b5d2324d6ebb48
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java index 2a39e25..0a51c45 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java @@ -370,7 +370,23 @@ public class TomcatWarComponent extends MBeanResourceComponent<TomcatVHostCompon mbeanOperation.invoke(paramValues);
if (!WarOperation.DESTROY.equals(operation)) { - String state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); + String state = null; + try { + // check to see if the mbean is truly active + state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); + } catch (Exception e) { + // if not active an exception may be thrown + state = WarMBeanState.STOPPED; + // try "state" for Tomcat 5.5 + try { + int stateInt = (Integer) this.webModuleMBean.getAttribute("state").refresh(); + if (stateInt == 1) { + state = WarMBeanState.STARTED; + } + } catch (Exception ex) { + // Ignore + } + } String expectedState = getExpectedPostExecutionState(operation); if (!state.equals(expectedState)) { throw new Exception("Failed to " + name + " webapp (value of the 'state' attribute of MBean '"
commit bc92133f9d4604dc57c6fe94fe900436a68a6e55 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:17:22 2013 +0200
[BZ 921194] Connectors are not properly discovered and therefore are unavailable.. from 00e594847fe67da46f8976df58b5d2324d6ebb48.
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java index 7a65a73..32566d5 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java @@ -132,12 +132,14 @@ public class TomcatConnectorDiscoveryComponent extends MBeanResourceDiscoveryCom if (connectorON != null) { EmsBean connectorBean = connection.getBean(connectorON); EmsAttribute executorNameAttrib = connectorBean.getAttribute("executorName"); - Object executorNameValue = executorNameAttrib.getValue(); - if (executorNameValue != null) { - String executorName = executorNameValue.toString(); - if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { - pluginConfiguration.put(new PropertySimple( - TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); + if (executorNameAttrib != null) { + Object executorNameValue = executorNameAttrib.getValue(); + if (executorNameValue != null) { + String executorName = executorNameValue.toString(); + if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { + pluginConfiguration.put(new PropertySimple( + TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); + } } } }
commit d582952ce48e1554794de9f22c724a37cb663644 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 15:13:02 2013 +0200
Fix BZ 865460 from 417fbb59817edf64a93d3cca00f2c51926379ab2
Conflicts:
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java index ead4956..0a95069 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatUserDatabaseComponent.java @@ -51,7 +51,6 @@ public class TomcatUserDatabaseComponent extends MBeanResourceComponent<TomcatSe if (TomcatGroupComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) { name = report.getResourceConfiguration().getSimple("groupname").getStringValue(); newRoles = report.getResourceConfiguration().getSimple(TomcatGroupComponent.CONFIG_ROLES); - report.getResourceConfiguration().remove(TomcatGroupComponent.CONFIG_ROLES); objectName = String.format("Users:type=Group,groupname="%s",database=UserDatabase", name); operation = "createGroup"; } else if (TomcatRoleComponent.RESOURCE_TYPE_NAME.equals(resourceTypeName)) {
commit e1e4350fd2242a3c18da547cc1212fa857ca5ea2 Author: jfclere jfclere@neo2.gva.redhat.com Date: Wed Apr 10 14:33:38 2013 +0200
fix for BZ: 707349 from e7d48240474fba87f1a3c4118de4618fd2c8b32d.
Conflicts:
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java index 32566d5..7a65a73 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorDiscoveryComponent.java @@ -132,14 +132,12 @@ public class TomcatConnectorDiscoveryComponent extends MBeanResourceDiscoveryCom if (connectorON != null) { EmsBean connectorBean = connection.getBean(connectorON); EmsAttribute executorNameAttrib = connectorBean.getAttribute("executorName"); - if (executorNameAttrib != null) { - Object executorNameValue = executorNameAttrib.getValue(); - if (executorNameValue != null) { - String executorName = executorNameValue.toString(); - if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { - pluginConfiguration.put(new PropertySimple( - TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); - } + Object executorNameValue = executorNameAttrib.getValue(); + if (executorNameValue != null) { + String executorName = executorNameValue.toString(); + if (!executorName.isEmpty() && !executorName.equalsIgnoreCase("Internal")) { + pluginConfiguration.put(new PropertySimple( + TomcatConnectorComponent.PLUGIN_CONFIG_SHARED_EXECUTOR, executorName)); } } } diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java index 0a51c45..2a39e25 100644 --- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java +++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarComponent.java @@ -370,23 +370,7 @@ public class TomcatWarComponent extends MBeanResourceComponent<TomcatVHostCompon mbeanOperation.invoke(paramValues);
if (!WarOperation.DESTROY.equals(operation)) { - String state = null; - try { - // check to see if the mbean is truly active - state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); - } catch (Exception e) { - // if not active an exception may be thrown - state = WarMBeanState.STOPPED; - // try "state" for Tomcat 5.5 - try { - int stateInt = (Integer) this.webModuleMBean.getAttribute("state").refresh(); - if (stateInt == 1) { - state = WarMBeanState.STARTED; - } - } catch (Exception ex) { - // Ignore - } - } + String state = (String) this.webModuleMBean.getAttribute("stateName").refresh(); String expectedState = getExpectedPostExecutionState(operation); if (!state.equals(expectedState)) { throw new Exception("Failed to " + name + " webapp (value of the 'state' attribute of MBean '" diff --git a/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml index 653736f..97f410a 100644 --- a/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/tomcat/src/main/resources/META-INF/rhq-plugin.xml @@ -748,8 +748,7 @@ <c:simple-property name="connector" type="string" - description="Connector protocol connector. Note: Only available on Tomcat 7." - required="false" + description="Connector protocol connector." readOnly="true" /> <c:simple-property name="address"
commit 16de1c5dbeb3759ec0bfb36f69008d77f7f2d927 Author: Jirka Kremser jkremser@redhat.com Date: Wed Aug 14 19:19:52 2013 +0200
Alert view for a single storage node and its child resources.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java index cd0ec54..c99cf70c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java @@ -218,16 +218,18 @@ public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewNa } }.run(); } - -// @Override -// public ViewName getViewName() { -// return VIEW_ID; -// }
public static String getAlertsString(String prefix, int numOfUnackAlerts) { - return prefix - + (numOfUnackAlerts != 0 ? " <font color='#CC0000;'>(" + numOfUnackAlerts + ")</font>" : " (" + return getAlertsString(prefix, -1, numOfUnackAlerts); + } + + public static String getAlertsString(String prefix, int storageNodeId, int numOfUnackAlerts) { + String detailsUrl = "#" + VIEW_PATH + "/" + storageNodeId + "/Alerts"; + detailsUrl = StringUtility.escapeHtml(detailsUrl); + String value = prefix + + (numOfUnackAlerts != 0 ? " <span style='color: #CC0000;'>(" + numOfUnackAlerts + ")</span>" : " (" + numOfUnackAlerts + ")"); + return storageNodeId == -1 ? value : LinkManager.getHref(detailsUrl, value); }
private static final class TabInfo { @@ -274,7 +276,7 @@ public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewNa showTab(alertsTabInfo); } else if (backupTabInfo.name.getName().equals(viewId)) { showTab(backupTabInfo); - } else { + } else { //default showTab(tableTabInfo); table.renderView(viewPath); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java index 0821585..9fa55a6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java @@ -20,9 +20,11 @@ package org.rhq.enterprise.gui.coregui.client.admin.storage;
import java.util.ArrayList;
+import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Record; import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.types.ImageStyle; +import com.smartgwt.client.widgets.HTMLFlow; import com.smartgwt.client.widgets.Img; import com.smartgwt.client.widgets.grid.CellFormatter; import com.smartgwt.client.widgets.grid.ListGrid; @@ -30,7 +32,10 @@ import com.smartgwt.client.widgets.grid.ListGridField; import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.grid.SummaryFunction;
+import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.criteria.AlertCriteria; +import org.rhq.core.domain.criteria.StorageNodeCriteria; +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; @@ -38,6 +43,7 @@ import org.rhq.enterprise.gui.coregui.client.alert.AlertDataSource; import org.rhq.enterprise.gui.coregui.client.alert.AlertHistoryView; import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction; import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement; +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.StringUtility;
@@ -47,9 +53,45 @@ import org.rhq.enterprise.gui.coregui.client.util.StringUtility; */ public class StorageNodeAlertHistoryView extends AlertHistoryView { private boolean isGouped = true; + private final HTMLFlow header; + private final int storageNodeId;
public StorageNodeAlertHistoryView(String tableTitle, int[] resourceIds) { + this(tableTitle, resourceIds, null, -1); + } + + public StorageNodeAlertHistoryView(String tableTitle, int[] resourceIds, HTMLFlow header, int storageNodeId) { super(tableTitle, resourceIds); + this.header = header; + this.storageNodeId = storageNodeId; + } + + @Override + protected void onInit() { + super.onInit(); + if (header != null && storageNodeId != -1) { + StorageNodeCriteria criteria = new StorageNodeCriteria(); + criteria.addFilterId(storageNodeId); + GWTServiceLookup.getStorageService().findStorageNodesByCriteria(criteria, + new AsyncCallback<PageList<StorageNode>>() { + public void onSuccess(final PageList<StorageNode> storageNodes) { + if (storageNodes == null || storageNodes.isEmpty() || storageNodes.size() != 1) { + CoreGUI.getErrorHandler().handleError( + MSG.view_adminTopology_message_fetchServerFail(String.valueOf(storageNodeId))); + } + final StorageNode node = storageNodes.get(0); + header + .setContents("<div style='text-align: center; font-weight: bold; font-size: medium;'> Storage Node (" + + node.getAddress() + ")</div>"); + } + + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError( + MSG.view_adminTopology_message_fetchServerFail(String.valueOf(storageNodeId)) + " " + + caught.getMessage(), caught); + } + }); + } }
@Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java index 7a777b1..e085eb1 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDatasource.java @@ -215,8 +215,8 @@ public class StorageNodeDatasource extends RPCDataSource<StorageNodeLoadComposit } } int value = from.getUnackAlerts(); - record.setAttribute(FIELD_ALERTS.propertyName(), "New Alerts" - + (value != 0 ? " <span style='color: #CC0000;'>(" + value + ")</span>" : " (" + value + ")")); + record.setAttribute(FIELD_ALERTS.propertyName(), + StorageNodeAdminView.getAlertsString("New Alerts", node.getId(), value)); String memory = null; if (from.getHeapPercentageUsed() != null && from.getHeapPercentageUsed().getAggregate().getAvg() != null) memory = MeasurementConverterClient.format(from.getHeapPercentageUsed().getAggregate().getAvg(), from diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java index a5ae6eb..dc500f0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeDetailView.java @@ -36,6 +36,7 @@ import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.types.Overflow; import com.smartgwt.client.types.VisibilityMode; +import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.HTMLFlow; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.FormItem; @@ -51,6 +52,7 @@ import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowCo import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageList; +import org.rhq.core.domain.util.collection.ArrayUtils; import org.rhq.enterprise.gui.coregui.client.BookmarkableView; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.LinkManager; @@ -63,6 +65,7 @@ import org.rhq.enterprise.gui.coregui.client.util.Log; import org.rhq.enterprise.gui.coregui.client.util.MeasurementUtility; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedUtility; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -85,6 +88,7 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab private SectionStackSection detailsAndLoadSection; private StaticTextItem alertsItem; private HTMLFlow header; + private boolean alerts = false;
private volatile int initSectionCount = 0; private int unackAlerts = -1; @@ -107,6 +111,9 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab @Override protected void onInit() { super.onInit(); + if (alerts) { + return; + } StorageNodeCriteria criteria = new StorageNodeCriteria(); criteria.addFilterId(storageNodeId); criteria.fetchResource(true); @@ -189,7 +196,7 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab } else { unackAlerts = result.get(0); if (alertsItem != null) { - alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", unackAlerts)); + alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, unackAlerts)); } } } @@ -203,6 +210,9 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab @Override protected void onDraw() { super.onDraw(); + if (alerts) { + return; + }
// wait until we have all of the sections before we show them. We don't use InitializableView because, // it seems they are not supported (in the applicable renderView()) at this level. @@ -284,8 +294,9 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab TimestampCellFormatter.DATE_TIME_FORMAT_LONG));
alertsItem = new StaticTextItem(FIELD_ALERTS.propertyName(), FIELD_ALERTS.title()); + alertsItem.setPrompt("The number in brackets represents the number of unacknowledged alerts for this storage node."); if (unackAlerts != -1) { - alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", unackAlerts)); + alertsItem.setValue(StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, unackAlerts)); }
StaticTextItem memoryStatusItem = new StaticTextItem("memoryStatus", "Memory"); @@ -341,9 +352,9 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab }
private void prepareResourceConfigEditor(final StorageNodeConfigurationComposite configuration) { - LayoutSpacer spacer = new LayoutSpacer(); - spacer.setHeight(15); - StorageNodeConfigurationEditor editorView = new StorageNodeConfigurationEditor(configuration); + LayoutSpacer spacer = new LayoutSpacer(); + spacer.setHeight(15); + StorageNodeConfigurationEditor editorView = new StorageNodeConfigurationEditor(configuration); SectionStackSection section = new SectionStackSection("Configuration"); section.setItems(spacer, editorView); section.setExpanded(true); @@ -353,10 +364,40 @@ public class StorageNodeDetailView extends EnhancedVLayout implements Bookmarkab initSectionCount++; }
+ private void showAlertsForSingleStorageNode() { + GWTServiceLookup.getStorageService().findResourcesWithAlertDefinitions(new StorageNode(storageNodeId), + new AsyncCallback<Integer[]>() { + @Override + public void onFailure(Throwable caught) { + alerts = false; + Message message = new Message("foobar", Message.Severity.Warning); +// CoreGUI.goToView(VIEW_ID.getName(), message); + } + + @Override + public void onSuccess(Integer[] result) { + if (result == null || result.length == 0) { + onFailure(new Exception("foobaz")); + } else { + removeMember(sectionStack); + sectionStack.destroy(); + int[] resIds = ArrayUtils.unwrapArray(result); + Canvas alertsView = new StorageNodeAlertHistoryView("storageNode_" + storageNodeId + "_Alerts", + resIds, header, storageNodeId); + addMember(alertsView); + } + } + }); + } + @Override public void renderView(ViewPath viewPath) { -// if (viewPath.toString().endsWith("/Config")) { -// } + if (viewPath.toString().endsWith("/Alerts")) { + alerts = true; + showAlertsForSingleStorageNode(); + } else { + alerts = false; + } Log.debug("StorageNodeDetailView: " + viewPath); } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java index bd415b2..efe56e3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeTableView.java @@ -83,7 +83,7 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { @Override protected void doOnDraw() { super.doOnDraw(); - scheduleUnacknowledgedAlertsPollingJob(getListGrid()); +// scheduleUnacknowledgedAlertsPollingJob(getListGrid()); }
@Override @@ -153,8 +153,9 @@ public class StorageNodeTableView extends TableSection<StorageNodeDatasource> { public void onSuccess(List<Integer> result) { for (int i = 0; i < records.length; i++) { int value = result.get(i); + int storageNodeId = records[i].getAttributeAsInt("id"); records[i].setAttribute(FIELD_ALERTS.propertyName(), - StorageNodeAdminView.getAlertsString("New Alerts", value)); + StorageNodeAdminView.getAlertsString("New Alerts", storageNodeId, value)); listGrid.setData(records); } schedule(15 * 1000); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java index 957bf34..38829a5 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java @@ -76,6 +76,8 @@ public interface StorageGWTService extends RemoteService {
Integer[] findResourcesWithAlertDefinitions() throws RuntimeException;
+ Integer[] findResourcesWithAlertDefinitions(StorageNode storageNode) throws RuntimeException; + int findNotAcknowledgedStorageNodeAlertsCount() throws RuntimeException;
List<Integer> findNotAcknowledgedStorageNodeAlertsCounts(List<Integer> storageNodeIds) throws RuntimeException; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java index f7f7442..b7437e3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java @@ -116,6 +116,15 @@ public class StorageGWTServiceImpl extends AbstractGWTServiceImpl implements Sto }
@Override + public Integer[] findResourcesWithAlertDefinitions(StorageNode storageNode) throws RuntimeException { + try { + return storageNodeManager.findResourcesWithAlertDefinitions(storageNode); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override public int findNotAcknowledgedStorageNodeAlertsCount() throws RuntimeException { try { return storageNodeManager.findNotAcknowledgedStorageNodeAlerts(getSessionSubject()).size(); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index e925de2..d7085da 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -575,7 +575,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
@Override public Integer[] findResourcesWithAlertDefinitions(StorageNode storageNode) { - List<StorageNode> initialStorageNodes = getStorageNodes(); + List<StorageNode> initialStorageNodes = null; if (storageNode == null) { initialStorageNodes = getStorageNodes(); } else { @@ -625,7 +625,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
return configuration; } - + @Override @Asynchronous public void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) {
commit 55ddbbee65308be50f72bd4cf83964227363d708 Author: Jay Shaughnessy jshaughn@redhat.com Date: Wed Aug 14 11:20:02 2013 -0400
remove entries for stuff still in a branch
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 5182ef1..617593a 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -67,7 +67,7 @@ <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> + <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, java.lang.String, java.lang.String)</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
@@ -162,11 +162,4 @@ <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
- <difference> - <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> - <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>org.rhq.core.domain.bundle.BundleGroup updateBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> - <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> - </difference> - </differences>
commit bc51c512ff058eb800e2644288a709d1d2ada5d7 Author: Thomas Segismont tsegismo@redhat.com Date: Wed Aug 14 11:13:09 2013 +0200
Bug 956329 - Create new Managed Server using EAP 6 plug-in exposes server groups and socket binding groups from other resources
Introduced new expressionScope attribute in RHQ config XSD for option source node (updated config parser, PropertyOptionSource entity and database schema accordingly)
Updated ConfigurationGWTService and ConfigurationManagerBean: now when filling enumeratedValues we look at expressionScope attribute to narrow down search results if expressionScope is 'baseResource'
Updated as7 plugin to use new expressionScope attribute for Managed Server resource configuration attributes
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/ConfigurationMetadataParser.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/ConfigurationMetadataParser.java index 4fa4558e..35ef00a 100644 --- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/ConfigurationMetadataParser.java +++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/metadata/ConfigurationMetadataParser.java @@ -1,24 +1,20 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2008 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, 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. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. + * GNU 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. + * 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.core.clientapi.agent.metadata;
@@ -40,6 +36,7 @@ import org.rhq.core.clientapi.descriptor.configuration.ConfigurationProperty; import org.rhq.core.clientapi.descriptor.configuration.ConfigurationTemplateDescriptor; import org.rhq.core.clientapi.descriptor.configuration.ConstraintType; import org.rhq.core.clientapi.descriptor.configuration.DynamicProperty; +import org.rhq.core.clientapi.descriptor.configuration.ExpressionScope; import org.rhq.core.clientapi.descriptor.configuration.FloatConstraintType; import org.rhq.core.clientapi.descriptor.configuration.IntegerConstraintType; import org.rhq.core.clientapi.descriptor.configuration.ListProperty; @@ -256,6 +253,11 @@ public class ConfigurationMetadataParser { throw new IllegalArgumentException("Filter expression must be less than 40 chars long"); } optionsSource.setFilter(source.getFilter()); + ExpressionScope expressionScope = source.getExpressionScope(); + if (expressionScope != null) { + optionsSource.setExpressionScope(PropertyOptionsSource.ExpressionScope.fromValue(expressionScope + .value())); + } String expression = source.getExpression(); if (expression == null || expression.isEmpty()) throw new IllegalArgumentException("Expression must not be empty"); diff --git a/modules/core/client-api/src/main/resources/rhq-configuration.xsd b/modules/core/client-api/src/main/resources/rhq-configuration.xsd index 4b706d8..d5e186b 100644 --- a/modules/core/client-api/src/main/resources/rhq-configuration.xsd +++ b/modules/core/client-api/src/main/resources/rhq-configuration.xsd @@ -479,7 +479,11 @@ Expressions are written in the syntax of the search bar.</xs:documentation> </xs:annotation> </xs:attribute> - + <xs:attribute name="expressionScope" use="optional" default="unlimited" type="config:expressionScope"> + xs:annotation + xs:documentationA scope for expression searches. Default value is 'unlimited'.</xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType>
<xs:complexType name="option"> @@ -607,4 +611,16 @@ </xs:restriction> </xs:simpleType>
+ <xs:simpleType name="expressionScope"> + xs:annotation + xs:documentationA scope for expression searches. Must be one of 'unlimited' or 'baseResource'. + 'unlimited' means that search results may include any resource in inventory. 'baseResource' narrows down to the + top level server or service.</xs:documentation> + </xs:annotation> + <xs:restriction base="xs:string"> + <xs:enumeration value="unlimited"/> + <xs:enumeration value="baseResource"/> + </xs:restriction> + </xs:simpleType> + </xs:schema> diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml index a3c82c2..2e8e4b8 100644 --- a/modules/core/dbutils/pom.xml +++ b/modules/core/dbutils/pom.xml @@ -17,7 +17,7 @@ <description>Database schema setup, upgrade and other utilities</description>
<properties> - <db.schema.version>2.135</db.schema.version> + <db.schema.version>2.136</db.schema.version> <rhq.ds.type-mapping>${rhq.test.ds.type-mapping}</rhq.ds.type-mapping> <rhq.ds.server-name>${rhq.test.ds.server-name}</rhq.ds.server-name> <rhq.ds.db-name>${rhq.test.ds.db-name}</rhq.ds.db-name> diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml index d5d937e..1328915 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml @@ -65,6 +65,7 @@ <column name="LINK_TO_TARGET" type="BOOLEAN" required="false"/> <column name="FILTER" type="VARCHAR2" required="false" size="40"/> <column name="EXPRESSION" type="VARCHAR2" required="true" size="400"/> + <column name="EXPRESSION_SCOPE" type="VARCHAR2" required="true" size="12" default="unlimited"/> <column name="TARGET_TYPE" type="VARCHAR2" required="true" size="20"/> <column name="PROPERTY_DEF_ID" type="INTEGER" required="false" references="RHQ_CONFIG_PROP_DEF"/> </table> diff --git a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml index 341f0b2..6f42345 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -1,4 +1,3 @@ - <project name="db-upgrade" default="upgrade" basedir=".">
<!-- @@ -2180,6 +2179,11 @@
</schemaSpec>
+ <schemaSpec version="2.136"> + <schema-addColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" columnType="VARCHAR2" precision="12"/> + <schema-alterColumn table="RHQ_CONFIG_PD_OSRC" column="EXPRESSION_SCOPE" nullable="false" default="unlimited"/> + </schemaSpec> + </dbupgrade> </target> </project> diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyOptionsSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyOptionsSource.java index 70c9a1f..7b34d0b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyOptionsSource.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyOptionsSource.java @@ -1,27 +1,25 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2011 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, 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. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. + * GNU 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. + * 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.core.domain.configuration.definition;
+import static org.rhq.core.domain.configuration.definition.PropertyOptionsSource.ExpressionScope.UNLIMITED; + import java.io.Serializable;
import javax.persistence.Column; @@ -54,8 +52,15 @@ public class PropertyOptionsSource implements Serializable{
@Column(name="LINK_TO_TARGET") private boolean linkToTarget; + private String filter; + + @Column(name="EXPRESSION_SCOPE") + @Enumerated(EnumType.STRING) + private ExpressionScope expressionScope; + private String expression; + @Column(name="TARGET_TYPE") @Enumerated(EnumType.STRING) private TargetType targetType; @@ -65,6 +70,7 @@ public class PropertyOptionsSource implements Serializable{ PropertyDefinitionSimple propertyDefinition;
public PropertyOptionsSource() { + expressionScope = UNLIMITED; }
public void setTarget(String target) { @@ -83,6 +89,10 @@ public class PropertyOptionsSource implements Serializable{ this.expression = expression; }
+ public void setExpressionScope(ExpressionScope expressionScope) { + this.expressionScope = expressionScope; + } + public boolean isLinkToTarget() { return linkToTarget; } @@ -95,10 +105,22 @@ public class PropertyOptionsSource implements Serializable{ return expression; }
+ public ExpressionScope getExpressionScope() { + return expressionScope; + } + public TargetType getTargetType() { return targetType; }
+ public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + public enum TargetType { GROUP("group"), PLUGIN("plugin"), @@ -123,15 +145,30 @@ public class PropertyOptionsSource implements Serializable{ } } return valueOf(v); -// throw new IllegalArgumentException(v.toString()); } }
- public int getId() { - return id; - } + public enum ExpressionScope { + UNLIMITED("unlimited"), // + BASE_RESOURCE("baseResource");
- public void setId(int id) { - this.id = id; + private final String value; + + ExpressionScope(String v) { + value = v; + } + + public String value() { + return value; + } + + public static ExpressionScope fromValue(String v) { + for (ExpressionScope f : ExpressionScope.values()) { + if (f.value.equals(v)) { + return f; + } + } + return valueOf(v); + } } } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java index c54d987..8fc65a8 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java @@ -1,24 +1,20 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2012 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, 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. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. + * GNU 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. + * 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.core.domain.resource;
@@ -1837,7 +1833,7 @@ public class Resource implements Comparable<Resource>, Serializable {
final Resource resource = (Resource) o;
- if ((uuid != null) ? (!uuid.equals(resource.uuid)) : (resource.uuid != null)) { + if ((getUuid() != null) ? (!getUuid().equals(resource.getUuid())) : (resource.getUuid() != null)) { return false; }
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/util/ResourceUtility.java b/modules/core/domain/src/main/java/org/rhq/core/domain/util/ResourceUtility.java index 748a66e..649edd8 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/util/ResourceUtility.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/util/ResourceUtility.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2012 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -13,17 +13,21 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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.core.domain.util;
+import static org.rhq.core.domain.resource.ResourceCategory.PLATFORM; + import java.util.LinkedHashSet; import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceType;
/** @@ -32,7 +36,7 @@ import org.rhq.core.domain.resource.ResourceType; * @since 4.4 * @author Ian Springer */ -public abstract class ResourceUtility { +public class ResourceUtility {
public static Resource getChildResource(Resource parent, ResourceType type, String key) { for (Resource resource : parent.getChildResources()) { @@ -68,7 +72,27 @@ public abstract class ResourceUtility { return acceptedChildResources; }
+ /** + * Returns the base server or service of the specified <code>resource</code>. + * + * @param resource + * @return the base server or service of the specified <code>resource</code>. + * @throws IllegalArgumentException if <code>resource</code> is null + */ + public static Resource getBaseServerOrService(Resource resource) { + if (resource == null) { + throw new IllegalArgumentException("resource is null"); + } + Resource current, parent = resource; + do { + current = parent; + parent = current.getParentResource(); + } while (parent != null && parent.getResourceType().getCategory() != PLATFORM); + return current; + } + private ResourceUtility() { + // Defensive }
} diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/util/ResourceUtilityTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/util/ResourceUtilityTest.java new file mode 100644 index 0000000..259166c --- /dev/null +++ b/modules/core/domain/src/test/java/org/rhq/core/domain/util/ResourceUtilityTest.java @@ -0,0 +1,84 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +package org.rhq.core.domain.util; + +import static org.rhq.core.domain.resource.ResourceCategory.PLATFORM; +import static org.rhq.core.domain.resource.ResourceCategory.SERVER; +import static org.rhq.core.domain.resource.ResourceCategory.SERVICE; +import static org.rhq.core.domain.util.ResourceUtility.getBaseServerOrService; +import static org.testng.Assert.assertSame; + +import org.testng.annotations.Test; + +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.resource.ResourceType; + +/** + * @author Thomas Segismont + */ +public class ResourceUtilityTest { + + private static final ResourceType TEST_PLATFORM_TYPE = new ResourceType("test platform", "test plugin", PLATFORM, + null); + private static final ResourceType TEST_TOP_LEVEL_SERVER_TYPE = new ResourceType("test topLevelServer", + "test plugin", SERVER, null); + + @Test(expectedExceptions = { IllegalArgumentException.class }) + public void getBaseServerOrServiceShouldThrowIllegalArgumentExceptionOnNull() throws Exception { + getBaseServerOrService(null); + } + + @Test + public void getBaseServerOrServiceOfPlatform() throws Exception { + Resource platform = new Resource(); + platform.setResourceType(TEST_PLATFORM_TYPE); + assertSame(platform, getBaseServerOrService(platform)); + } + + @Test + public void getBaseServerOrServiceOfTopLevelServer() throws Exception { + Resource topLevelServer = new Resource(); + topLevelServer.setResourceType(TEST_TOP_LEVEL_SERVER_TYPE); + assertSame(topLevelServer, getBaseServerOrService(topLevelServer)); + } + + @Test + public void getBaseServerOrServiceOfTopLevelService() throws Exception { + Resource topLevelService = new Resource(); + topLevelService.setResourceType(new ResourceType("test topLevelService", "test plugin", SERVICE, null)); + assertSame(topLevelService, getBaseServerOrService(topLevelService)); + } + + @Test + public void getBaseServerOrServiceOfNestedService() throws Exception { + ResourceType testServiceType = new ResourceType("test service", "test plugin", SERVICE, + TEST_TOP_LEVEL_SERVER_TYPE); + Resource service = new Resource(); + service.setResourceType(testServiceType); + Resource topLevelServer = new Resource(); + topLevelServer.setResourceType(TEST_TOP_LEVEL_SERVER_TYPE); + topLevelServer.addChildResource(service); + Resource platform = new Resource(); + platform.setResourceType(TEST_PLATFORM_TYPE); + platform.addChildResource(topLevelServer); + assertSame(topLevelServer, getBaseServerOrService(service)); + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ConfigurationGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ConfigurationGWTService.java index 06207cd..ad7ac3b 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ConfigurationGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ConfigurationGWTService.java @@ -1,3 +1,22 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + package org.rhq.enterprise.gui.coregui.client.gwt;
import java.util.List; @@ -88,6 +107,6 @@ public interface ConfigurationGWTService extends RemoteService { void deleteGroupResourceConfigurationUpdate(Integer groupId, Integer[] groupResourceConfigUpdateIds) throws RuntimeException;
- ConfigurationDefinition getOptionValuesForConfigDefinition(int resourceId, ConfigurationDefinition definition) - throws RuntimeException; + ConfigurationDefinition getOptionValuesForConfigDefinition(int resourceId, int parentResourceId, + ConfigurationDefinition definition) throws RuntimeException; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java index febc86d..983a8dd 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/detail/operation/schedule/AbstractOperationScheduleDetailsView.java @@ -1,8 +1,7 @@ /* * RHQ Management Platform - * Copyright 2010-2011, Red Hat Middleware LLC, and individual contributors - * as indicated by the @author tags. See the copyright.txt file in the - * distribution for a full listing of individual contributors. + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,8 +13,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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.enterprise.gui.coregui.client.inventory.common.detail.operation.schedule;
@@ -463,7 +462,7 @@ public abstract class AbstractOperationScheduleDetailsView extends }
ConfigurationGWTServiceAsync configurationService = GWTServiceLookup.getConfigurationService(); - configurationService.getOptionValuesForConfigDefinition(getResourceId(), parametersDefinition, + configurationService.getOptionValuesForConfigDefinition(getResourceId(), -1, parametersDefinition, new AsyncCallback<ConfigurationDefinition>() {
@Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java index 6a51e3d..b358bb3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/configuration/ResourceConfigurationEditView.java @@ -141,7 +141,7 @@ public class ResourceConfigurationEditView extends EnhancedVLayout implements Pr public void onTypesLoaded(ResourceType type) { ConfigurationGWTServiceAsync configurationService = GWTServiceLookup .getConfigurationService(); - configurationService.getOptionValuesForConfigDefinition(resource.getId(), + configurationService.getOptionValuesForConfigDefinition(resource.getId(), -1, type.getResourceConfigurationDefinition(), new AsyncCallback<ConfigurationDefinition>() { @Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java index 3aa37e0..a9fe9f3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/factory/ResourceFactoryConfigurationStep.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2010 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -13,8 +13,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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.enterprise.gui.coregui.client.inventory.resource.factory;
@@ -97,7 +97,7 @@ public class ResourceFactoryConfigurationStep extends AbstractWizardStep impleme this.startingConfig = wizard.getNewResourceStartingConfiguration();
ConfigurationGWTServiceAsync configurationService = GWTServiceLookup.getConfigurationService(); - configurationService.getOptionValuesForConfigDefinition(-1, def, + configurationService.getOptionValuesForConfigDefinition(-1, wizard.getParentResource().getId(), def, new AsyncCallback<ConfigurationDefinition>() { public void onSuccess(ConfigurationDefinition result) { createAndAddConfigurationEditor(result); 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 d351f7a..3520f82 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 @@ -1,3 +1,22 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + package org.rhq.enterprise.gui.coregui.server.gwt;
import java.util.ArrayList; @@ -352,11 +371,11 @@ public class ConfigurationGWTServiceImpl extends AbstractGWTServiceImpl implemen }
@Override - public ConfigurationDefinition getOptionValuesForConfigDefinition(int resourceId, ConfigurationDefinition definition) - throws RuntimeException { + public ConfigurationDefinition getOptionValuesForConfigDefinition(int resourceId, int parentResourceId, + ConfigurationDefinition definition) throws RuntimeException { try { ConfigurationDefinition def = configurationManager.getOptionsForConfigurationDefinition( - getSessionSubject(), resourceId, definition); + getSessionSubject(), resourceId, parentResourceId, definition); return SerialUtility.prepare(def, "ConfigurationService.getOptionValuesForPropertySimple"); } catch (Throwable t) { throw getExceptionToThrowToClient(t); diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java index 700cfc5..eef4c70 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBeanTest.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2011 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -13,8 +13,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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.enterprise.server.configuration;
@@ -776,7 +776,7 @@ public class ConfigurationManagerBeanTest extends AbstractEJB3Test { assert configurationDefinition != null : "Configuration Definition could not be located."; //retrieve the options for ConfigurationDefinition ConfigurationDefinition options = configurationManager.getOptionsForConfigurationDefinition(overlord, - newResource1.getId(), configurationDefinition); + newResource1.getId(), -1, configurationDefinition); assert options != null : "Unable able to retrieve options for resource with id [" + newResource1.getId() + "]."; assert !options.getPropertyDefinitions().entrySet().isEmpty() : "No PropertyDefinitionSimple instances found."; diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java index 8246626..6c078c6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerBean.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2011 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -13,8 +13,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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.enterprise.server.configuration;
@@ -38,6 +38,9 @@ import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.Query;
+import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Hibernate; @@ -96,6 +99,7 @@ import org.rhq.core.domain.util.OrderingField; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.PageOrdering; +import org.rhq.core.domain.util.ResourceUtility; import org.rhq.core.util.MessageDigestGenerator; import org.rhq.core.util.collection.ArrayUtils; import org.rhq.core.util.exception.ThrowableUtil; @@ -2534,26 +2538,37 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf
@Override public ConfigurationDefinition getOptionsForConfigurationDefinition(Subject subject, int resourceId, - ConfigurationDefinition def) { + int parentResourceId, ConfigurationDefinition def) { + + Resource resource = null, baseResource = null; + if (resourceId >= 0) { + resource = resourceManager.getResource(subject, resourceId); + } + if (parentResourceId >= 0) { + Resource parentResource = resourceManager.getResource(subject, parentResourceId); + baseResource = ResourceUtility.getBaseServerOrService(parentResource); + } else if (resource != null) { + baseResource = ResourceUtility.getBaseServerOrService(resource); + }
for (Map.Entry<String, PropertyDefinition> entry : def.getPropertyDefinitions().entrySet()) { PropertyDefinition pd = entry.getValue();
if (pd instanceof PropertyDefinitionSimple) { PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pd; - handlePDS(subject, resourceId, pds); + handlePDS(subject, resource, baseResource, pds);
} else if (pd instanceof PropertyDefinitionList) { PropertyDefinitionList pdl = (PropertyDefinitionList) pd; PropertyDefinition memberDef = pdl.getMemberDefinition(); if (memberDef instanceof PropertyDefinitionSimple) { PropertyDefinitionSimple pds = (PropertyDefinitionSimple) memberDef; - handlePDS(subject, resourceId, pds); + handlePDS(subject, resource, baseResource, pds); } else if (memberDef instanceof PropertyDefinitionMap) { PropertyDefinitionMap pdm = (PropertyDefinitionMap) memberDef; for (PropertyDefinition inner : pdm.getOrderedPropertyDefinitions()) { if (inner instanceof PropertyDefinitionSimple) { - handlePDS(subject, resourceId, (PropertyDefinitionSimple) inner); + handlePDS(subject, resource, baseResource, (PropertyDefinitionSimple) inner); } log.debug("3 ____[ " + inner.toString() + " in " + pdl.toString() + " ]____ not yet supported"); } @@ -2565,7 +2580,7 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf PropertyDefinitionMap pdm = (PropertyDefinitionMap) pd; for (PropertyDefinition inner : pdm.getOrderedPropertyDefinitions()) { if (inner instanceof PropertyDefinitionSimple) { - handlePDS(subject, resourceId, (PropertyDefinitionSimple) inner); + handlePDS(subject, resource, baseResource, (PropertyDefinitionSimple) inner); } else { log.debug("4 ____[ " + inner.toString() + " in " + pdm.toString() + " ]____ not yet supported"); } @@ -2583,21 +2598,20 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf * @param subject Subject of the caller - may limit search results * @param pds the PropertyDefinitionSimple to work on */ - private void handlePDS(final Subject subject, int resourceId, PropertyDefinitionSimple pds) { + private void handlePDS(final Subject subject, Resource resource, Resource baseResource, PropertyDefinitionSimple pds) {
if (pds.getOptionsSource() != null) { // evaluate the source parameters PropertyOptionsSource pos = pds.getOptionsSource(); PropertyOptionsSource.TargetType tt = pos.getTargetType(); String expression = pos.getExpression(); + PropertyOptionsSource.ExpressionScope expressionScope = pos.getExpressionScope(); String filter = pos.getFilter(); Pattern filterPattern = null; if (filter != null) filterPattern = Pattern.compile(filter);
if (tt == PropertyOptionsSource.TargetType.RESOURCE || tt == PropertyOptionsSource.TargetType.CONFIGURATION) { - List<Resource> resources = null; - CriteriaQuery<Resource, ResourceCriteria> resourcesPaged = null; ResourceCriteria criteria = new ResourceCriteria();
//Use CriteriaQuery to automatically chunk/page through criteria query results @@ -2608,6 +2622,7 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf } };
+ Iterable<Resource> foundResources = null; if (tt == PropertyOptionsSource.TargetType.CONFIGURATION) { // split out expression part for target=configuration // return if no property specifier is given @@ -2617,10 +2632,15 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf
if (!"self".equals(expr)) { criteria.setSearchExpression(expr); - resourcesPaged = new CriteriaQuery<Resource, ResourceCriteria>(criteria, queryExecutor); - } else if (resourceId >= 0) { - resources = new ArrayList<Resource>(); - resources.add(resourceManager.getResourceById(subject, resourceId)); + foundResources = new CriteriaQuery<Resource, ResourceCriteria>(criteria, queryExecutor); + if (expressionScope == PropertyOptionsSource.ExpressionScope.BASE_RESOURCE && baseResource != null) { + foundResources = Iterables.filter(foundResources, new IsInBaseResourcePredicate( + baseResource)); + } + } else if (resource != null) { + ArrayList<Resource> resourceList = new ArrayList<Resource>(); + resourceList.add(resource); + foundResources = resourceList; } else { log.warn("Self reference requested but resource id is not valid." + "Option source expression:" + expression); @@ -2633,18 +2653,16 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf } } else { criteria.setSearchExpression(expression); - resourcesPaged = new CriteriaQuery<Resource, ResourceCriteria>(criteria, queryExecutor); - } - - if (resources != null) {//process resources - for (Resource resource : resources) { - processPropertyOptionsSource(pds, tt, expression, filterPattern, resource); - } - } else {// process resourcesPaged(CriteriaQuery parsing) - for (Resource resource : resourcesPaged) { - processPropertyOptionsSource(pds, tt, expression, filterPattern, resource); + foundResources = new CriteriaQuery<Resource, ResourceCriteria>(criteria, queryExecutor); + if (expressionScope == PropertyOptionsSource.ExpressionScope.BASE_RESOURCE && baseResource != null) { + foundResources = Iterables.filter(foundResources, new IsInBaseResourcePredicate( + baseResource)); } } + + for (Resource foundResource : foundResources) { + processPropertyOptionsSource(pds, tt, expression, filterPattern, foundResource); + } } else if (tt == PropertyOptionsSource.TargetType.GROUP) { // spinder 2-15-13: commenting out this code below as we don't appear to be using any of it. Half done. // // for groups we need to talk to the group manager @@ -2772,4 +2790,19 @@ public class ConfigurationManagerBean implements ConfigurationManagerLocal, Conf
return true; } + + private static final class IsInBaseResourcePredicate implements Predicate<Resource> { + + private Resource baseResource; + + private IsInBaseResourcePredicate(Resource baseResource) { + this.baseResource = baseResource; + } + + @Override + public boolean apply(Resource resource) { + Resource baseServerOrService = ResourceUtility.getBaseServerOrService(resource); + return baseResource.equals(baseServerOrService); + } + } } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java index 9fc43ce..640b17d 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/ConfigurationManagerLocal.java @@ -1,6 +1,6 @@ /* * RHQ Management Platform - * Copyright (C) 2005-2008 Red Hat, Inc. + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -13,8 +13,8 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * 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.enterprise.server.configuration;
@@ -473,7 +473,7 @@ public interface ConfigurationManagerLocal extends ConfigurationManagerRemote { GroupPluginConfigurationUpdateCriteria criteria);
ConfigurationDefinition getOptionsForConfigurationDefinition(Subject subject, int resourceId, - ConfigurationDefinition def); + int parentResourceId, ConfigurationDefinition def);
/** * Dedicated method for supporting resource upgrade of plugin configuration. Similar to diff --git a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml index 162c3a1..1fd2e82 100644 --- a/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/jboss-as-7/src/main/resources/META-INF/rhq-plugin.xml @@ -1701,13 +1701,13 @@ <resource-configuration> <!-- IF you add properties here, you also need to update org.rhq.modules.plugins.jbossas7.ManagedASComponent.loadResourceConfiguration --> <c:simple-property name="hostname" displayName="Name of the host to put the server on" required="true" readOnly="true"> - <c:option-source target="resource" expression="type=^Host$ plugin=&pluginName;"/> + <c:option-source target="resource" expression="type=^Host$ plugin=&pluginName;" expressionScope="baseResource"/> </c:simple-property> <c:simple-property name="group" readOnly="false" displayName="Server Group" description="Server Group this instance belongs to."> - <c:option-source target="resource" expression="type=ServerGroup"/> + <c:option-source target="resource" expression="type=ServerGroup" expressionScope="baseResource"/> </c:simple-property> - <c:simple-property name="socket-binding-group" readOnly="false" displayName="Socket binding group" description="Socket bindings to use" required="true" default="standard-sockets"> - <c:option-source target="resource" expression="type=SocketBindingGroup"/> + <c:simple-property name="socket-binding-group" readOnly="false" displayName="Socket binding group" description="Socket bindings to use" required="true"> + <c:option-source target="resource" expression="type=SocketBindingGroup" expressionScope="baseResource"/> </c:simple-property> <c:simple-property name="socket-binding-port-offset" readOnly="false" displayName="Port Offset" type="integer" default="0" description="Offset to the base ports"/> <c:simple-property name="auto-start" displayName="Autostart" default="false" type="boolean"/>
commit c8145af10e3cb79bbf03f6b95f16bde6568498d6 Author: Thomas Segismont tsegismo@redhat.com Date: Wed Aug 14 16:51:00 2013 +0200
Bug 846362 - [jboss-as5] Shutdown max wait time "shared" between different resources
diff --git a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java index b96a2cc..2ced390 100644 --- a/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java +++ b/modules/plugins/jboss-as-5/src/main/java/org/rhq/plugins/jbossas5/ApplicationServerOperationsDelegate.java @@ -1,27 +1,28 @@ /* - * Jopr Management Platform - * Copyright (C) 2005-2009 Red Hat, Inc. + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, 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. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License and the GNU Lesser General Public License - * for more details. + * GNU 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. + * 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.jbossas5;
+import static java.util.concurrent.TimeUnit.MINUTES; +import static org.rhq.core.util.StringUtil.isBlank; +import static org.rhq.plugins.jbossas5.ApplicationServerPluginConfigurationProperties.START_WAIT_MAX_PROP; +import static org.rhq.plugins.jbossas5.ApplicationServerPluginConfigurationProperties.STOP_WAIT_MAX_PROP; + import java.io.File; import java.util.List; import java.util.Map; @@ -54,7 +55,7 @@ import org.rhq.core.system.SystemInfo; * @author Jay Shaughnessy */ public class ApplicationServerOperationsDelegate { - + private static class ExecutionFailedException extends Exception {
private static final long serialVersionUID = 1L; @@ -76,12 +77,12 @@ public class ApplicationServerOperationsDelegate { super(cause); } } - + /** - * max amount of time to wait for server to show as unavailable after + * default max amount of time to wait for server to show as unavailable after * executing stop - in milliseconds */ - private static long STOP_WAIT_MAX = 1000L * 150; // 2.5 minutes + private static final long DEFAULT_STOP_WAIT_MAX = 1000L * 150; // 2.5 minutes
/** * amount of time to wait between availability checks when performing a stop @@ -95,8 +96,8 @@ public class ApplicationServerOperationsDelegate { */ private static final long STOP_WAIT_FINAL = 1000L * 30; // 30 seconds
- /** max amount of time to wait for start to complete - in milliseconds */ - private static long START_WAIT_MAX = 1000L * 300; // 5 minutes + /** default max amount of time to wait for start to complete - in milliseconds */ + private static final long DEFAULT_START_WAIT_MAX = 1000L * 300; // 5 minutes
/** * amount of time to wait between availability checks when performing a @@ -503,17 +504,9 @@ public class ApplicationServerOperationsDelegate { AvailabilityType avail; //detect whether startWaitMax property has been set. Configuration pluginConfig = serverComponent.getResourceContext().getPluginConfiguration(); - PropertySimple property = pluginConfig - .getSimple(ApplicationServerPluginConfigurationProperties.START_WAIT_MAX_PROP); - //if set and valid, update startWaitMax value - if ((property != null) && (property.getIntegerValue() != null)) { - int newValue = property.getIntegerValue(); - if (newValue >= 1) { - START_WAIT_MAX = 1000L * 60 * newValue; - } - } + long startWaitMax = getMaxWait(pluginConfig.getSimple(START_WAIT_MAX_PROP), DEFAULT_START_WAIT_MAX); while (((avail = this.serverComponent.getAvailability()) == AvailabilityType.DOWN) - && (System.currentTimeMillis() < (start + START_WAIT_MAX))) { + && (System.currentTimeMillis() < (start + startWaitMax))) { try { Thread.sleep(START_WAIT_INTERVAL); } catch (InterruptedException e) { @@ -528,17 +521,9 @@ public class ApplicationServerOperationsDelegate { AvailabilityType avail; //detect whether stopWaitMax property has been set. Configuration pluginConfig = serverComponent.getResourceContext().getPluginConfiguration(); - PropertySimple property = pluginConfig - .getSimple(ApplicationServerPluginConfigurationProperties.STOP_WAIT_MAX_PROP); - //if set and valid update stopWaitMax value - if ((property != null) && (property.getIntegerValue() != null)) { - int newValue = property.getIntegerValue(); - if (newValue >= 1) { - STOP_WAIT_MAX = 1000L * 60 * newValue; - } - } + long stopWaitMax = getMaxWait(pluginConfig.getSimple(STOP_WAIT_MAX_PROP), DEFAULT_STOP_WAIT_MAX); while (((avail = this.serverComponent.getAvailability()) == AvailabilityType.UP) - && (System.currentTimeMillis() < (start + STOP_WAIT_MAX))) { + && (System.currentTimeMillis() < (start + stopWaitMax))) { try { Thread.sleep(STOP_WAIT_INTERVAL); } catch (InterruptedException e) { @@ -556,6 +541,22 @@ public class ApplicationServerOperationsDelegate { return avail; }
+ private long getMaxWait(PropertySimple propertySimple, long defaultValueInMillis) { + if (propertySimple == null || isBlank(propertySimple.getStringValue())) { + return defaultValueInMillis; + } + try { + long valueInMinutes = Long.parseLong(propertySimple.getStringValue()); + if (valueInMinutes > 0) { + return MINUTES.toMillis(valueInMinutes); + } else { + return defaultValueInMillis; + } + } catch (NumberFormatException e) { + return defaultValueInMillis; + } + } + /** * Return the absolute path of this JBoss server's start script (e.g. * "C:\opt\jboss-5.1.0.GA\bin\run.sh"). @@ -659,4 +660,3 @@ public class ApplicationServerOperationsDelegate { } } } -
commit 357cd0c0ffe244a42d6c43dffc3b80d7648be347 Author: John Sanda jsanda@redhat.com Date: Tue Aug 13 23:56:39 2013 -0400
adding test impl of StorageClusterSettingsManagerLocal
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java new file mode 100644 index 0000000..3ac61e4 --- /dev/null +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.java @@ -0,0 +1,26 @@ +package org.rhq.enterprise.server.storage; + +import javax.ejb.Stateless; + +import org.rhq.core.domain.auth.Subject; + +/** + * @author John Sanda + */ +@Stateless +public class FakeStorageClusterSettingsManagerBean implements StorageClusterSettingsManagerLocal { + + @Override + public StorageClusterSettings getClusterSettings(Subject subject) { + StorageClusterSettings settings = new StorageClusterSettings(); + settings.setGossipPort(7100); + settings.setCqlPort(9042); + + return settings; + } + + @Override + public void setClusterSettings(Subject subject, StorageClusterSettings clusterSettings) { + //To change body of implemented methods use File | Settings | File Templates. + } +}
commit 01e5b0a219d79ee80d2724d5aa03a000e3915910 Author: John Sanda jsanda@redhat.com Date: Tue Aug 13 23:06:17 2013 -0400
attempting to fix server itest failures
I am not sure why but DiscoveryBossBeanTest has been failing due to calls to StorageClusterSettingsManagerBean made by StorageNodeManagerBean. I am deploying a test impl for StorageClusterSettingsManager to see if it resovles the issues. There is no need to deploy the production EJB. It is just a thin wrapper around SystemManagerBean, and it can/should be tested separately.
diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java index 44a4646..0f1c6fb 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java @@ -88,6 +88,7 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginService; import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceMBean; import org.rhq.enterprise.server.scheduler.SchedulerService; import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean; +import org.rhq.enterprise.server.storage.FakeStorageClusterSettingsManagerBean; import org.rhq.enterprise.server.storage.StorageClientManagerBean; import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.test.AssertUtils; @@ -352,6 +353,8 @@ public abstract class AbstractEJB3Test extends Arquillian { .create("/rhq-server.jar/org/rhq/enterprise/server/core/StartupBean$1.class")); testEar.delete(ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/core/ShutdownListener.class")); + testEar.delete(ArchivePaths + .create("/rhq-server.jar/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.class"));
//replace the above startup beans with stripped down versions testEar.add(new ClassAsset(StrippedDownStartupBean.class), ArchivePaths @@ -359,6 +362,8 @@ public abstract class AbstractEJB3Test extends Arquillian { testEar.add(new ClassAsset(StrippedDownStartupBeanPreparation.class), ArchivePaths .create("/rhq-server.jar/org/rhq/enterprise/server/test/" + "StrippedDownStartupBeanPreparation.class")); + testEar.add(new ClassAsset(FakeStorageClusterSettingsManagerBean.class), ArchivePaths + .create("/rhq-server.jar/org/rhq/enterprise/server/storage/FakeStorageClusterSettingsManagerBean.class")); testEar.addAsManifestResource(new ByteArrayAsset("<beans/>".getBytes()), ArchivePaths.create("beans.xml"));
// add the test classes to the deployment diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 9e41692..e925de2 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -36,10 +36,6 @@ import java.util.Map; import java.util.Queue; import java.util.Set;
-import org.rhq.enterprise.server.storage.StorageClusterSettings; -import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerBean; -import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; - import javax.ejb.Asynchronous; import javax.ejb.EJB; import javax.ejb.Stateless; @@ -88,6 +84,9 @@ import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.rest.reporting.MeasurementConverter; import org.rhq.enterprise.server.scheduler.SchedulerLocal; +import org.rhq.enterprise.server.storage.StorageClusterSettings; +import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerLocal; +import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; import org.rhq.enterprise.server.util.CriteriaQueryGenerator; import org.rhq.enterprise.server.util.CriteriaQueryRunner; import org.rhq.enterprise.server.util.LookupUtil; @@ -154,7 +153,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN private ResourceManagerLocal resourceManager;
@EJB - private StorageClusterSettingsManagerBean storageClusterSettingsManager; + private StorageClusterSettingsManagerLocal storageClusterSettingsManager;
@EJB private StorageNodeOperationsHandlerLocal storageNodeOperationsHandler; diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java index 3e10a2f..9418bca 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerBean.java @@ -3,7 +3,7 @@ package org.rhq.enterprise.server.storage; import java.util.Map;
import javax.ejb.EJB; -import javax.ejb.Singleton; +import javax.ejb.Stateless;
import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.common.composite.SystemSetting; @@ -13,12 +13,13 @@ import org.rhq.enterprise.server.system.SystemManagerLocal; /** * @author John Sanda */ -@Singleton -public class StorageClusterSettingsManagerBean { +@Stateless +public class StorageClusterSettingsManagerBean implements StorageClusterSettingsManagerLocal {
@EJB private SystemManagerLocal systemManager;
+ @Override public StorageClusterSettings getClusterSettings(Subject subject) { SystemSettings settings = systemManager.getSystemSettings(subject); Map<String, String> settingsMap = settings.toMap(); @@ -41,6 +42,7 @@ public class StorageClusterSettingsManagerBean { return clusterSettings; }
+ @Override public void setClusterSettings(Subject subject, StorageClusterSettings clusterSettings) { SystemSettings settings = new SystemSettings(); settings.put(SystemSetting.STORAGE_CQL_PORT, Integer.toString(clusterSettings.getCqlPort())); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java new file mode 100644 index 0000000..cb63bc4 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClusterSettingsManagerLocal.java @@ -0,0 +1,15 @@ +package org.rhq.enterprise.server.storage; + +import javax.ejb.Local; + +import org.rhq.core.domain.auth.Subject; + +/** + * @author John Sanda + */ +@Local +public interface StorageClusterSettingsManagerLocal { + StorageClusterSettings getClusterSettings(Subject subject); + + void setClusterSettings(Subject subject, StorageClusterSettings clusterSettings); +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java index 3e0eed8..1bf3cec 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageNodeOperationsHandlerBean.java @@ -63,7 +63,7 @@ public class StorageNodeOperationsHandlerBean implements StorageNodeOperationsHa private OperationManagerLocal operationManager;
@EJB - private StorageClusterSettingsManagerBean storageClusterSettingsManager; + private StorageClusterSettingsManagerLocal storageClusterSettingsManager;
@EJB private StorageClientManagerBean storageClientManager;
commit e273adc3ecfaf894f44fd50f21d1d2b39a643966 Author: Mike Thompson mithomps@redhat.com Date: Tue Aug 13 15:32:30 2013 -0700
[BZ 949750] - Chart hovers fail to render in IE. Availability Chart hover fix.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java index 64c355d..59d4c75 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java @@ -250,6 +250,44 @@ public class AvailabilityOverUnderGraphType implements AvailabilityGraphType { .attr("opacity", ".75") .attr("fill", function (d) { return calcBarFill(d); + }).on("mouseover",function (d) { + + var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat), + dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat), + availStart = new Date(+d.availStart), + xPosition = parseFloat($wnd.d3.select(this).attr("x")), + availTooltipDiv = $wnd.d3.select("#availTooltip") + .style("left", xPosition + "px") + .style("top", "0px"); + + availTooltipDiv.select("#availTooltipLabel") + .text(availChartContext.hoverBarAvailabilityLabel); + + availTooltipDiv + .select("#availTooltipType") + .text(d.availTypeMessage); + + availTooltipDiv + .select("#availTooltipStartDate") + .text(dateFormatter(availStart)); + + availTooltipDiv + .select("#availTooltipStartTime") + .text(timeFormatter(availStart)); + + availTooltipDiv + .select("#availTooltipDurationLabel") + .text(availChartContext.hoverBarLabel); + + availTooltipDiv + .select("#availTooltipDuration") + .text(d.availDuration); + + //Show the tooltip + $wnd.d3.select("#availTooltip").classed("hidden", false); + }).on("mouseout", function () { + //Hide the tooltip + $wnd.d3.select("#availTooltip").classed("hidden", true); });
xAxis.tickFormat($wnd.rhqCommon.getD3CustomTimeFormat(availChartContext.chartXaxisTimeFormatHours, availChartContext.chartXaxisTimeFormatHoursMinutes)); @@ -295,42 +333,11 @@ public class AvailabilityOverUnderGraphType implements AvailabilityGraphType { }
- - function createHovers() { - $wnd.jQuery('svg rect.availBars').tipsy({ - gravity: 's', - html: true, - trigger: 'hover', - title: function () { - var d = this.__data__; - return formatHovers(d); - }, - show: function (e, el) { - el.css({ 'z-index': '990000'}) - } - }); - } - - - function formatHovers(d) { - var timeFormatter = $wnd.d3.time.format(availChartContext.chartHoverTimeFormat), - dateFormatter = $wnd.d3.time.format(availChartContext.chartHoverDateFormat), - availStart = new Date(+d.availStart); - - return '<div class="chartHoverEnclosingDiv">' + - '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarAvailabilityLabel + ': </span><span style="width:50px;">' + d.availTypeMessage + '</span></div>' + - '<div class="chartHoverAlignLeft"><span>' + dateFormatter(availStart) + ' ' + timeFormatter(availStart) + '</span></div>' + - '<div class="chartHoverAlignLeft"><span >' + availChartContext.hoverBarLabel + ': </span><span style="width:50px;">' + d.availDuration + '</span></div>' + - '</div>'; - - } - return { // Public API draw: function (availChartContext) { "use strict"; drawBars(availChartContext); - createHovers(); } }; // end public closure
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java index 3fc0192..6e3b590 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/monitoring/avail/AvailabilityD3GraphView.java @@ -83,7 +83,22 @@ public class AvailabilityD3GraphView<T extends AvailabilityGraphType> extends En divAndSvgDefs.append("<div id="availChart-" + availabilityGraphType.getChartId() + "" ><svg xmlns="http://www.w3.org/2000/svg%5C" version="1.1" style="height:65px;">"); divAndSvgDefs.append(getSvgDefs()); - divAndSvgDefs.append("</svg></div>"); + divAndSvgDefs.append("</svg>"); + divAndSvgDefs.append("<div id="availTooltip" class="hidden" >"); + divAndSvgDefs.append("<div>"); + divAndSvgDefs.append("<span id="availTooltipLabel" class="availTooltipLabel"></span>"); + divAndSvgDefs.append("<span> : </span>"); + divAndSvgDefs.append("<span id="availTooltipType" style="width:40px;font-weight:bold;"></span>"); + divAndSvgDefs.append("<span> - </span>"); + divAndSvgDefs.append("<span id="availTooltipDuration" ></span>"); + divAndSvgDefs.append("<div/>"); + divAndSvgDefs.append("<div>"); + divAndSvgDefs.append("<span id="availTooltipStartDate" ></span>"); + divAndSvgDefs.append("<span> </span>"); + divAndSvgDefs.append("<span id="availTooltipStartTime" ></span>"); + divAndSvgDefs.append("</div>"); + divAndSvgDefs.append("</div>"); // end availTooltipDiv + divAndSvgDefs.append("</div>"); HTMLFlow graph = new HTMLFlow(divAndSvgDefs.toString()); graph.setWidth100(); graph.setHeight(65); diff --git a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css index 2dbd79b..6a004b4 100644 --- a/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css +++ b/modules/enterprise/gui/coregui/src/main/webapp/css/charts.css @@ -156,3 +156,39 @@ rect.low { font-weight: bold; color: #70c4e2; } + +#availTooltip { + z-index: 990000; + position: absolute; + width: 150px; + height: auto; + padding: 5px; + background-color: #000; + opacity: 0.55; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4); + pointer-events: none; +} + +#availTooltip.hidden { + display: none; +} + +#availTooltip div { + margin: 0; + font-family: Arial, Verdana, sans-serif; + font-size: 9px; + color: #d3d3d6; +} + +.availTooltipLabel { + width: 40px; + font-weight: bold; + color: #d3d3d6; +} + +
commit 83cf625882610f53d1de3e6e335066c5e58f43f7 Author: Simeon Pinder spinder@fulliautomatix.conchfritter.com Date: Mon Aug 12 15:17:15 2013 -0400
[BZ 990576] fix issue with available groups status update speed, guard against client failures and add more logging.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java index c4e7145..4cb1275 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java @@ -72,7 +72,8 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c public static final String FIELD_DESCRIPTION = "description"; final TextItem searchTextItem = new TextItem(); protected int cursorPosition; - private static int retryAttempt = 0; + private static int retryAttempt = 0;//limit retries on failure + private static int noProgressAttempts = 0;//limit really slow attempt parse times
//override the selector key for ldap group selection. protected String getSelectorKey() { @@ -263,6 +264,7 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c groupQueryStatus.setIcons(failIcon); groupQueryStatus.setDefaultValue(MSG.view_adminRoles_failLdapGroupsSettings()); CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdapGroupsSettings(), caught); + Log.debug(MSG.view_adminRoles_failLdapGroupsSettings()); }
@Override @@ -308,6 +310,7 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c retryAttempt++; if (retryAttempt > 3) { cancel();//kill thread + Log.debug(MSG.view_adminRoles_failLdapRetry()); retryAttempt = 0; } } @@ -339,6 +342,10 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c pageCount = Integer.valueOf(value); } } + + if (resultCountValue == 0) { + noProgressAttempts++; + } //Update status information String warnTooManyResults = MSG.view_adminRoles_ldapWarnTooManyResults(); String warnQueryTakingLongResults = MSG.view_adminRoles_ldapWarnQueryTakingLongResults(); @@ -378,12 +385,15 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c if (resultCountValue > 20000) {//results throttled adviceItem.setValue(tooManyResults); adviceItem.setTooltip(tooManyResults); + Log.debug(tooManyResults);//log error to client. } else if ((current - start) >= 10 * 1000) {// took longer than 10s adviceItem.setValue(queryTookLongResults); adviceItem.setTooltip(queryTookLongResults); + Log.debug(queryTookLongResults);//log error to client. } else if (pageCount >= 20) {// required more than 20 pages of results adviceItem.setValue(queryTookManyPagesResults); adviceItem.setTooltip(queryTookManyPagesResults); + Log.debug(queryTookManyPagesResults);//log error to client. } else {//simple success. groupQueryStatus.setDefaultValue(success); groupQueryStatus.setIcons(successIcon); @@ -391,8 +401,19 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c adviceItem.setTooltip(none); adviceItem.setDisabled(true); } + noProgressAttempts = 0; //now cancel the timer cancel(); + } else if (noProgressAttempts >= 10) {//availGroups query stuck on server side + //cancel the timer. + cancel(); + String clientSideQuitting = MSG.view_adminRoles_failLdapCancelling();//catch all + adviceItem.setDisabled(false); + groupQueryStatus.setIcons(attentionIcon); + adviceItem.setValue(clientSideQuitting); + adviceItem.setTooltip(clientSideQuitting); + noProgressAttempts = 0; + Log.debug(clientSideQuitting);//log error to client. } availableGroupDetails.markForRedraw(); } 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 2422c35..c253fbd 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 @@ -512,9 +512,11 @@ view_adminRoles_assignedSubjects = Assigned Subjects view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name. view_adminRoles_failLdap = Failed to determine if LDAP configured - assuming no LDAP. view_adminRoles_failLdapAvailableGroups = Failed: Unable to retrieve status for latest AvailableGroups() call. +view_adminRoles_failLdapCancelling = Client unable to proceed. Cancelling all future available groups status checks for this thread. Likely 1)LDAP server communication failures or 2)ldap query checking inexplicably failed. view_adminRoles_failLdapGroups = Failed to retrieve available LDAP groups - assuming no LDAP groups. view_adminRoles_failLdapGroupsRole = Failed to load LDAP groups available for role. view_adminRoles_failLdapGroupsSettings = Failed to retrieve system settings details for LDAP groups. +view_adminRoles_failLdapRetry = Retried 3 times. Cancelling future available group requests. view_adminRoles_failRoles = Failed to fetch roles. view_adminRoles_globalPerms = Global Permissions view_adminRoles_ldapGroups = LDAP Groups diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index 7c6d1d3..c4db863 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -531,9 +531,11 @@ view_adminRoles_assignedSubjects = Přiřazené subjekty view_adminRoles_failCreateRoleWithExistingName = Nepodařilo se vytvořit roli s existujícím jménem [{0}]. Použíjte prosím jiné jméno. view_adminRoles_failLdap = Nepodařilo se určit je-li LDAP nastaven - předpokládám, že LDAP není přítomen. ##view_adminRoles_failLdapAvailableGroups = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. +##view_adminRoles_failLdapCancelling = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. view_adminRoles_failLdapGroups = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. view_adminRoles_failLdapGroupsRole = Nepodařilo se získat informace o LDAP skupinách pro roli. ##view_adminRoles_failLdapGroupsSettings = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. +##view_adminRoles_failLdapRetry = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. view_adminRoles_failRoles = Nepodařilo se získat role. view_adminRoles_globalPerms = Globalní povolení view_adminRoles_ldapGroups = LDAP skupiny diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index ce7677d..a1e43f3 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -509,9 +509,11 @@ view_adminRoles_assignedSubjects = Zugewisene Benutzer view_adminRoles_failCreateRoleWithExistingName = Konnte die Rolle mit dem existierenden Namen [{0}] nicht anlegen. Bitte wählen Sie einen anderen Namen. view_adminRoles_failLdap = Konnte nicht ermitteln, ob LDAP konfiguriert ist - gehe von keiner LDAP-Konfiguration aus. ##view_adminRoles_failLdapAvailableGroups = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. +##view_adminRoles_failLdapCancelling = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. view_adminRoles_failLdapGroups = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. view_adminRoles_failLdapGroupsRole = Konnte die LDAP-Gruppen für die Rolle nicht laden. ##view_adminRoles_failLdapGroupsSettings = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. +##view_adminRoles_failLdapRetry = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. view_adminRoles_failRoles = Konnte die Rollen nicht laden. view_adminRoles_globalPerms = Applikationsweite Rechte view_adminRoles_ldapGroups = LDAP-Gruppen diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index 87b4d0c..c9a319b 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -508,9 +508,11 @@ view_adminRoles_assignedSubjects = 割り当てられたSubjects ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name. view_adminRoles_failLdap = LDAPが構成されたかどうかの決定に失敗しました - LDAPが無いことを仮定します ##view_adminRoles_failLdapAvailableGroups = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します +##view_adminRoles_failLdapCancelling = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します view_adminRoles_failLdapGroups = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します view_adminRoles_failLdapGroupsRole = ロールのために利用可能なLDAPグループをロードするのに失敗しました ##view_adminRoles_failLdapGroupsSettings = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します +##view_adminRoles_failLdapRetry = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します view_adminRoles_failRoles = ロールの取り出しに失敗しました view_adminRoles_globalPerms = グローバル権限 view_adminRoles_ldapGroups = LDAPグループ diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index 351335d..627c73b 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -459,9 +459,11 @@ view_adminRoles_assignedSubjects = 할당된 Subjects view_adminRoles_failCreateRoleWithExistingName = 기존 이름 [{0}]과 역할을 만들지 못했습니다. 다른 이름을 사용하십시오. view_adminRoles_failLdap = LDAP이 설정되었는지 여부의 결정에 실패했습니다 - LDAP이 없는 것을 가정합니다. ##view_adminRoles_failLdapAvailableGroups = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. +##view_adminRoles_failLdapCancelling = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. view_adminRoles_failLdapGroups = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. view_adminRoles_failLdapGroupsRole = 역할을 위해 사용가능한 LDAP 그룹을 로드하느데 실패했습니다. ##view_adminRoles_failLdapGroupsSettings = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. +##view_adminRoles_failLdapRetry = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. view_adminRoles_failRoles = 역할 제거에 실패했습니다. view_adminRoles_globalPerms = 글로벌 권한 view_adminRoles_ldapGroups = LDAP 그룹 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index e47dc01..65a9fba 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -514,9 +514,11 @@ view_adminRoles_assignedSubjects = Perfis Associados ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please Use another name. view_adminRoles_failLdap = Falha ao determinar se o LDAP foi configurado - assumindo como LDAP n\u00E3o configurado. ##view_adminRoles_failLdapAvailableGroups = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. +##view_adminRoles_failLdapCancelling = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. view_adminRoles_failLdapGroups = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. view_adminRoles_failLdapGroupsRole = Falha ao carregar grupos do LDAP dispon\u00EDveis para o perfil. ##view_adminRoles_failLdapGroupsSettings = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. +##view_adminRoles_failLdapRetry = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. view_adminRoles_failRoles = Falha ao recuperar perfis. view_adminRoles_globalPerms = Permiss\u00F5es Globais view_adminRoles_ldapGroups = Grupos LDAP diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index 4004a35..6088218 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2595,14 +2595,15 @@ view_adminRoles_assignedSubjects = Назначенные субъекты ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name. view_adminRoles_failLdap = Не удалось определить, настроен ли LDAP - предположительно LDAP отсутствует. ##view_adminRoles_failLdapAvailableGroups = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют +##view_adminRoles_failLdapCancelling = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют view_adminRoles_failLdapGroups = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют view_adminRoles_failLdapGroupsRole = Не удалось загрузить LDAP группы, доступные для роли. ##view_adminRoles_failLdapGroupsSettings = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют +##view_adminRoles_failLdapRetry = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют view_adminRoles_failRoles = Не удалось получить роли. view_adminRoles_globalPerms = Глобальные полномочия view_adminRoles_ldapGroups = LDAP-группы view_adminRoles_ldapGroupsReadOnly = данные LDAP групп доступны только для чтения -##view_adminRoles_noLdap = The LDAP security integration is not configured. To configure LDAP, go to <a {0}>{1}</a>. ##view_adminRoles_ldapGroupsSettingsReadOnly = данные LDAP групп доступны только для чтения ##view_adminRoles_ldapQueryPageSize = Полномочия ресурса ##view_adminRoles_ldapTooManyResults = данные LDAP групп доступны только для чтения @@ -2611,6 +2612,7 @@ view_adminRoles_ldapGroupsReadOnly = данные LDAP групп доступн ##view_adminRoles_ldapWarnParsingManyPagesResults = данные LDAP групп доступны только для чтения ##view_adminRoles_ldapWarnQueryTakingLongResults = данные LDAP групп доступны только для чтения ##view_adminRoles_ldapWarnTooManyResults = данные LDAP групп доступны только для чтения +##view_adminRoles_noLdap = The LDAP security integration is not configured. To configure LDAP, go to <a {0}>{1}</a>. view_adminRoles_permissions_autoselecting_configureRead_implied = Автоматически отключено CONFIGURE_WRITE полномочие, поскольку отсутствует CONFIGURE_READ... view_adminRoles_permissions_autoselecting_configureWrite_implied = Автоматически выбрано CONFIGURE_READ полномочие, поскольку CONFIGURE_WRITE подразумевает, что ... ##view_adminRoles_permissions_autoselecting_manageBundleGroups_implied = Autoselected View Bundles, which is granted by Manage Bundle Groups... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index 1364008..ccf79fb 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -502,9 +502,11 @@ view_adminRoles_assignedSubjects = \u5206\u914d\u7684\u4e3b\u9898 ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please Use another name. view_adminRoles_failLdap = \u65e0\u6cd5\u786e\u5b9aLDAP - \u5047\u5b9a\u6ca1\u6709LDAP. ##view_adminRoles_failLdapAvailableGroups = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. +##view_adminRoles_failLdapCancelling = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. view_adminRoles_failLdapGroups = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. view_adminRoles_failLdapGroupsRole = \u52a0\u8f7dLDAP\u7ec4\u89d2\u8272\u5931\u8d25. ##view_adminRoles_failLdapGroupsSettings = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. +##view_adminRoles_failLdapRetry = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. view_adminRoles_failRoles = \u53d6\u5f97\u89d2\u8272\u5931\u8d25. view_adminRoles_globalPerms = \u5168\u5c40\u6388\u6743 view_adminRoles_ldapGroups = LDAP\u7ec4 diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java index dc53a3c..5c8031d 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java @@ -604,7 +604,13 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" entry.put("name", name); entry.put("description", description); groupDetailsMap.add(entry); - resultCount++; + + resultCount++;//monitor the number of groups returned during this query. + groupQueryResultCount = resultCount;//update result count + if (groupQueryPageCount == 0) { + groupQueryPageCount++; + } + groupQueryCurrentTime = System.currentTimeMillis(); } }
commit cb621eb1489858c7e3177c2ba922a6fbfbcd9f7b Author: Simeon Pinder spinder@fulliautomatix.conchfritter.com Date: Fri Aug 9 16:46:29 2013 -0400
[BZ 990576] add I18N for new fields.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java index 8d53b82..c4e7145 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java @@ -97,16 +97,13 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c int groupPanelWidth = 375; int groupPanelHeight = 150;
- // final TextItem search = new TextItem("search", - // MSG.common_title_search()); - // Structure the display area into two separate display regions // Available Groups region final DynamicForm availableGroupDetails = new DynamicForm(); { availableGroupDetails.setWidth(groupPanelWidth); availableGroupDetails.setHeight(groupPanelHeight); - availableGroupDetails.setGroupTitle("Available Groups Results"); + availableGroupDetails.setGroupTitle(MSG.common_title_ldapGroupsAvailable()); availableGroupDetails.setIsGroup(true); availableGroupDetails.setWrapItemTitles(false); //add itemChanged handler to listen for changes to SearchItem @@ -129,21 +126,21 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c } }); } - final TextItem resultCountItem = new TextItem("resultCount", "Groups Found"); + final TextItem resultCountItem = new TextItem("resultCount", MSG.common_title_groupsFound()); { resultCountItem.setCanEdit(false); resultCountItem.setWidth("100%"); } - final TextItem pageCountItem = new TextItem("pageCount", "Query Pages Parsed"); + final TextItem pageCountItem = new TextItem("pageCount", MSG.common_title_queryPagesParsed()); { pageCountItem.setCanEdit(false); pageCountItem.setWidth("100%"); } - final TextAreaItem adviceItem = new TextAreaItem("advice", "Suggest"); + final TextAreaItem adviceItem = new TextAreaItem("advice", MSG.common_title_suggest()); { adviceItem.setWidth("100%"); adviceItem.setHeight(20); - String feedback = "(None)"; + String feedback = MSG.common_val_none(); adviceItem.setValue(feedback); adviceItem.setTooltip(feedback); adviceItem.setDisabled(true); @@ -162,13 +159,12 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c } }); } - // final TextItem search = new TextItem("search", - // MSG.common_title_search()); + //Customize Search component { - searchTextItem.setName("search"); - searchTextItem.setTitle("Filter[results below]"); + searchTextItem.setName(MSG.common_title_search()); + searchTextItem.setTitle(MSG.common_title_filterResultsBelow()); searchTextItem.setWidth("100%"); - searchTextItem.setTooltip("Start typing here to only show groups containing the typed characters."); + searchTextItem.setTooltip(MSG.common_msg_typeToFilterResults()); } final FormItemIcon loadingIcon = new FormItemIcon(); final FormItemIcon successIcon = new FormItemIcon(); @@ -186,8 +182,8 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c final StaticTextItem groupQueryStatus = new StaticTextItem(); { groupQueryStatus.setName("groupQueryStatus"); - groupQueryStatus.setTitle("Query Progress"); - groupQueryStatus.setDefaultValue("Loading..."); + groupQueryStatus.setTitle(MSG.common_title_queryProgress()); + groupQueryStatus.setDefaultValue(MSG.common_msg_loading()); groupQueryStatus.setIcons(loadingIcon); } availableGroupDetails.setItems(resultCountItem, pageCountItem, groupQueryStatus, adviceItem, searchTextItem); @@ -197,21 +193,22 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c { ldapGroupSettings.setWidth(groupPanelWidth); ldapGroupSettings.setHeight(groupPanelHeight); - ldapGroupSettings.setGroupTitle("[Read Only] Ldap Group Settings. Edit in 'System Settings'"); + ldapGroupSettings.setGroupTitle(MSG.view_adminRoles_ldapGroupsSettingsReadOnly()); ldapGroupSettings.setIsGroup(true); ldapGroupSettings.setWrapItemTitles(false); } - final TextItem groupSearch = new TextItem("groupSearch", "Search Filter"); + final TextItem groupSearch = new TextItem("groupSearch", MSG.view_admin_systemSettings_LDAPFilter_name()); { groupSearch.setCanEdit(false); groupSearch.setWidth("100%"); } - final TextItem groupMember = new TextItem("groupMember", "Member Filter"); + final TextItem groupMember = new TextItem("groupMember", MSG.view_admin_systemSettings_LDAPGroupMember_name()); { groupMember.setCanEdit(false); groupMember.setWidth("100%"); } - final CheckboxItem groupQueryPagingItem = new CheckboxItem("groupQueryEnable", "Query Paging Enabled"); + final CheckboxItem groupQueryPagingItem = new CheckboxItem("groupQueryEnable", + MSG.view_admin_systemSettings_LDAPGroupUsePaging_name()); { groupQueryPagingItem.setCanEdit(false); groupQueryPagingItem.setValue(false); @@ -221,12 +218,14 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c //You have to set this attribute groupQueryPagingItem.setAttribute("labelAsTitle", true); } - final TextItem groupQueryPagingCountItem = new TextItem("groupQueryCount", "Query Page Size"); + final TextItem groupQueryPagingCountItem = new TextItem("groupQueryCount", + MSG.view_adminRoles_ldapQueryPageSize()); { groupQueryPagingCountItem.setCanEdit(false); groupQueryPagingCountItem.setWidth("100%"); } - final CheckboxItem groupUsePosixGroupsItem = new CheckboxItem("groupUsePosixGroups", "Use Posix Enabled"); + final CheckboxItem groupUsePosixGroupsItem = new CheckboxItem("groupUsePosixGroups", + MSG.view_admin_systemSettings_LDAPGroupUsePosixGroup_name()); { groupUsePosixGroupsItem.setCanEdit(false); groupUsePosixGroupsItem.setValue(false); @@ -262,9 +261,8 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c @Override public void onFailure(Throwable caught) { groupQueryStatus.setIcons(failIcon); - groupQueryStatus.setDefaultValue("Fail: Unable to retrieve system settings."); - //TODO: update this message - CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); + groupQueryStatus.setDefaultValue(MSG.view_adminRoles_failLdapGroupsSettings()); + CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdapGroupsSettings(), caught); }
@Override @@ -291,10 +289,10 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c //launch operations to populate/refresh LDAP Group Query contents. final Timer availableGroupsTimer = new Timer() { public void run() { - final String attention = "Attention"; - final String success = "Success"; - final String none = "(None)"; - final String failed = "Failed"; + final String attention = MSG.common_status_attention(); + final String success = MSG.common_status_success(); + final String none = MSG.common_val_none(); + final String failed = MSG.common_status_failed(); //make request to RHQ about state of latest LDAP GWT request GWTServiceLookup.getLdapService().findAvailableGroupsStatus( new AsyncCallback<Set<Map<String, String>>>() { @@ -302,11 +300,11 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c public void onFailure(Throwable caught) { groupQueryStatus.setIcons(failIcon); groupQueryStatus.setDefaultValue(failed); - String adviceValue = "Failed: Unable to retrieve status for latest AvailableGroups() call."; + String adviceValue = MSG.view_adminRoles_failLdapAvailableGroups(); adviceItem.setValue(adviceValue); adviceItem.setTooltip(adviceValue); - //TODO: update this message - CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); + CoreGUI.getErrorHandler() + .handleError(MSG.view_adminRoles_failLdapAvailableGroups(), caught); retryAttempt++; if (retryAttempt > 3) { cancel();//kill thread @@ -342,9 +340,10 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c } } //Update status information - String warnTooManyResults = " A lot of results are being returned. Modify your 'Group Search Filter' to return fewer results."; - String warnQueryTakingLongResults = " Query taking a while to complete. Modify your 'Group Search Filter' to return fewer results."; - String warnParsingManyPagesResults = " Query requires a lot of pages. Modify your 'Group Search Page Size' to return more results per request."; + String warnTooManyResults = MSG.view_adminRoles_ldapWarnTooManyResults(); + String warnQueryTakingLongResults = MSG.view_adminRoles_ldapWarnQueryTakingLongResults(); + String warnParsingManyPagesResults = MSG.view_adminRoles_ldapWarnParsingManyPagesResults(); + boolean resultCountWarning = false; boolean pageCountWarning = false; boolean timePassingWarning = false; @@ -368,12 +367,11 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c //act on status details to add extra perf suggestions. Kill threads older than 30 mins long parseTime = System.currentTimeMillis() - ldapGroupSelectorRequestId; if ((queryCompleted) || (parseTime) > 30 * 60 * 1000) { - String tooManyResults = "Too many results to show all. Modify your 'Group Search Filter' to return fewer than 20000 results."; - String queryTookLongResults = " Query took " + parseTime - + " ms to complete. Modify your 'Group Search Filter' to return fewer results."; - String queryTookManyPagesResults = " Query required " - + pageCount - + " pages to complete. Modify 'Group Search Page Size' to return more results per request."; + String tooManyResults = MSG.view_adminRoles_ldapTooManyResults(); + String queryTookLongResults = MSG.view_adminRoles_ldapTookLongResults(parseTime + ""); + String queryTookManyPagesResults = MSG + .view_adminRoles_ldapTookManyPagesResults(pageCount + ""); + adviceItem.setDisabled(false); groupQueryStatus.setIcons(attentionIcon); groupQueryStatus.setDefaultValue(attention); 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 8f9fe56..2422c35 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 @@ -136,11 +136,13 @@ common_msg_noItemsToShow = No items to show common_msg_notYetImplemented = Not Yet Implemented common_msg_see_more = see more... common_msg_step_x_of_y = Step {0} of {1} +common_msg_typeToFilterResults = Start typing here to only show results containing the typed characters. common_severity_debug = Debug common_severity_error = Error common_severity_fatal = Fatal common_severity_info = Info common_severity_warn = Warn +common_status_attention = Attention common_status_canceled = Canceled common_status_deferred = Deferred common_status_failed = Failed @@ -192,11 +194,13 @@ common_title_edit = Edit? common_title_edit_mode = Edit Mode common_title_enabled = Enabled? common_title_end = End +common_title_filterResultsBelow = Filter[results below] common_title_generalProp = General Properties common_title_group = Group common_title_group_def_total = Group Definition Total common_title_group_member_health = Group Member Health common_title_groups = Groups +common_title_groupsFound = Groups Found common_title_help = Help common_title_host = Host common_title_id = ID @@ -210,6 +214,7 @@ common_title_kind = Kind common_title_lastUpdated = Last Updated common_title_lastUpdatedBy = Last Updated By common_title_ldapGroups = LDAP Groups +common_title_ldapGroupsAvailable = Available Groups Results common_title_mashup = Mashup common_title_members_reporting = Members Reporting common_title_message = Message @@ -234,6 +239,8 @@ common_title_platform_total = Platform Total common_title_plugin = Plugin common_title_port = Port common_title_providers = Providers +common_title_queryPagesParsed = Query Pages Parsed +common_title_queryProgress = Query Progress common_title_recent_alerts = Recent Alerts common_title_recent_bundle_deployments = Recent Bundle Deployments common_title_recent_configuration_updates = Recent Configuration Updates @@ -273,6 +280,7 @@ common_title_sort_order_tooltip = Sets sort order for results. common_title_start = Start common_title_status = Status common_title_stop = Stop +common_title_suggest = Suggest common_title_summary = Summary common_title_tag_cloud = Tag Cloud common_title_the = The @@ -503,12 +511,22 @@ view_adminRoles_assignedGroups = Assigned Resource Groups view_adminRoles_assignedSubjects = Assigned Subjects view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name. view_adminRoles_failLdap = Failed to determine if LDAP configured - assuming no LDAP. +view_adminRoles_failLdapAvailableGroups = Failed: Unable to retrieve status for latest AvailableGroups() call. view_adminRoles_failLdapGroups = Failed to retrieve available LDAP groups - assuming no LDAP groups. view_adminRoles_failLdapGroupsRole = Failed to load LDAP groups available for role. +view_adminRoles_failLdapGroupsSettings = Failed to retrieve system settings details for LDAP groups. view_adminRoles_failRoles = Failed to fetch roles. view_adminRoles_globalPerms = Global Permissions view_adminRoles_ldapGroups = LDAP Groups view_adminRoles_ldapGroupsReadOnly = LDAP group data is read only +view_adminRoles_ldapGroupsSettingsReadOnly = [Read Only] Ldap Group Settings. Edit in 'System Settings' +view_adminRoles_ldapQueryPageSize = Query Page Size +view_adminRoles_ldapTooManyResults = Too many results to show all. Modify your 'Group Search Filter' to return fewer than 20000 results. +view_adminRoles_ldapTookLongResults = Query took {0} ms to complete. Modify your 'Group Search Filter' to return fewer results. +view_adminRoles_ldapTookManyPagesResults = Query required {0} pages to complete. Modify 'Group Search Page Size' to return more results per request. +view_adminRoles_ldapWarnParsingManyPagesResults = Query requires a lot of pages. Modify your 'Group Search Page Size' to return more results per request. +view_adminRoles_ldapWarnQueryTakingLongResults = \ Query taking a while to complete. Modify your 'Group Search Filter' to return fewer results. +view_adminRoles_ldapWarnTooManyResults = \ A lot of results are being returned. Modify your 'Group Search Filter' to return fewer results. view_adminRoles_noLdap = The LDAP security integration is not configured. To configure LDAP, go to <a {0}>{1}</a>. view_adminRoles_permissions_autoselecting_configureRead_implied = Autodeselected CONFIGURE_WRITE permission, since lack of CONFIGURE_READ implies lack of it... view_adminRoles_permissions_autoselecting_configureWrite_implied = Autoselected CONFIGURE_READ permission, since CONFIGURE_WRITE implies it... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index a71ddd1..7c6d1d3 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -159,11 +159,13 @@ common_msg_noItemsToShow = Žádné položky k zobrazení common_msg_notYetImplemented = Ještě nebylo implementováno common_msg_see_more = více... common_msg_step_x_of_y = Krok {0} z {1} +##common_msg_typeToFilterResults = Ještě nebylo implementováno common_severity_debug = Ladění common_severity_error = Chyba common_severity_fatal = Fatální common_severity_info = Informační common_severity_warn = Varování +##common_status_attention = Úspěch common_status_canceled = Zrušeno common_status_deferred = Odloženo common_status_failed = Selhalo @@ -215,11 +217,13 @@ common_title_edit_mode = Editační mód common_title_enabled = Povoleno? common_title_end = Konec common_title_favorites = Oblíbené +##common_title_filterResultsBelow = Oblíbené common_title_generalProp = Obecné vlastnosti common_title_group = Skupina common_title_group_def_total = Definic skupin celkem common_title_group_member_health = Zdraví člena skupiny common_title_groups = Skupiny +##common_title_groupsFound = Skupiny common_title_help = Nápověda common_title_host = Host common_title_icon = Ikona @@ -234,6 +238,7 @@ common_title_kind = Druh common_title_lastUpdated = Naposledy modifikováno common_title_lastUpdatedBy = Naposledy modifikoval common_title_ldapGroups = LDAP skupiny +##common_title_ldapGroupsAvailable = LDAP skupiny common_title_mashup = Mashup common_title_members_reporting = Reportování členů common_title_message = Zpráva @@ -258,6 +263,8 @@ common_title_platform_total = Celkem platforem common_title_plugin = Zásuvný modul common_title_port = Port common_title_providers = Poskytovatelé +##common_title_queryPagesParsed = LDAP skupiny +##common_title_queryProgress = LDAP skupiny common_title_recent_alerts = Nedávné výstrahy common_title_recent_bundle_deployments = Nedávno nasazené balíky common_title_recent_configuration_updates = Nedávno změněné konfigurace @@ -297,6 +304,7 @@ common_title_sort_order_tooltip = Nastaví řazení pro výsledky. common_title_start = Start common_title_status = Stav common_title_stop = Stop +##common_title_suggest = Shrnutí common_title_summary = Shrnutí common_title_tag_cloud = Tag cloud common_title_timestamp = Datum/Čas @@ -522,12 +530,22 @@ view_adminRoles_assignedGroups = Přiřazené skupiny zdrojů view_adminRoles_assignedSubjects = Přiřazené subjekty view_adminRoles_failCreateRoleWithExistingName = Nepodařilo se vytvořit roli s existujícím jménem [{0}]. Použíjte prosím jiné jméno. view_adminRoles_failLdap = Nepodařilo se určit je-li LDAP nastaven - předpokládám, že LDAP není přítomen. +##view_adminRoles_failLdapAvailableGroups = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. view_adminRoles_failLdapGroups = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. view_adminRoles_failLdapGroupsRole = Nepodařilo se získat informace o LDAP skupinách pro roli. +##view_adminRoles_failLdapGroupsSettings = Nepodařilo se získat informace o LDAP skupinách - předpokládám, že LDAP není přítomen. view_adminRoles_failRoles = Nepodařilo se získat role. view_adminRoles_globalPerms = Globalní povolení view_adminRoles_ldapGroups = LDAP skupiny view_adminRoles_ldapGroupsReadOnly = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapGroupsSettingsReadOnly = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapQueryPageSize = Oprávnění zdroje +##view_adminRoles_ldapTooManyResults = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapTookLongResults = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapTookManyPagesResults = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapWarnParsingManyPagesResults = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapWarnQueryTakingLongResults = data LDAP skupiny jsou jen pro čtení +##view_adminRoles_ldapWarnTooManyResults = data LDAP skupiny jsou jen pro čtení view_adminRoles_noLdap = Integrace LDAP není nakonfigurována. K nastavení řízení bezpečnosti přes LDAP prosím navštivte <a {0}>{1}</a>. view_adminRoles_permissions_autoselecting_configureRead_implied = Automaticky odoznačeno CONFIGURE_WRITE povolení, protože absence CONFIGURE_READ to implikuje... view_adminRoles_permissions_autoselecting_configureWrite_implied = Automaticky označeno CONFIGURE_READ povolení, protože CONFIGURE_WRITE jej implikuje... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index d85b08e..ce7677d 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -139,11 +139,13 @@ common_msg_noItemsToShow = Keine Einträge vorhanden common_msg_notYetImplemented = Noch nicht implementiert common_msg_see_more = mehr ... common_msg_step_x_of_y = Schritt {0} von {1} +##common_msg_typeToFilterResults = Noch nicht implementiert common_severity_debug = Debug common_severity_error = Fehler common_severity_fatal = Fatal common_severity_info = Information common_severity_warn = Warnung +##common_status_attention = Erfolg common_status_canceled = Abgebrochen common_status_deferred = Verzögert common_status_failed = Fehlgeschlagen @@ -199,6 +201,7 @@ common_title_group = Gruppe common_title_group_def_total = Anzahl Gruppen-Definitionen common_title_group_member_health = Zustand der Gruppenmitglieder common_title_groups = Gruppen +##common_title_groupsFound = Gruppen common_title_help = Hilfe common_title_host = Rechner common_title_id = ID @@ -211,6 +214,7 @@ common_title_kind = Art common_title_lastUpdated = Zuletzt aktualisiert common_title_lastUpdatedBy = Zuletzt aktualisiert durch common_title_ldapGroups = LDAP-Gruppen +##common_title_ldapGroupsAvailable = LDAP-Gruppen ##common_title_mashup = Mashup common_title_members_reporting = Anzahl berichtender Mitglieder common_title_message = Nachricht @@ -235,6 +239,8 @@ common_title_platform_total = Anzahl Platformen common_title_plugin = Plugin common_title_port = Port common_title_providers = Anbieter +##common_title_queryPagesParsed = LDAP-Gruppen +##common_title_queryProgress = LDAP-Gruppen common_title_recent_alerts = Kürzlich ausgelöste Alarme common_title_recent_bundle_deployments = Kürzliche Bundle-Deployments common_title_recent_configuration_updates = Frische Konfigurationsaktualisierungen @@ -274,6 +280,7 @@ common_title_sort_order_tooltip = Legt die Sortierreihenfolge für Ergebnisse fe common_title_start = Start common_title_status = Status common_title_stop = Stop +##common_title_suggest = Zusammenfassung common_title_summary = Zusammenfassung common_title_tag_cloud = Tag-Wolke common_title_the = Die @@ -501,12 +508,22 @@ view_adminRoles_assignedGroups = Zugewiesene Ressourcen-Gruppen view_adminRoles_assignedSubjects = Zugewisene Benutzer view_adminRoles_failCreateRoleWithExistingName = Konnte die Rolle mit dem existierenden Namen [{0}] nicht anlegen. Bitte wählen Sie einen anderen Namen. view_adminRoles_failLdap = Konnte nicht ermitteln, ob LDAP konfiguriert ist - gehe von keiner LDAP-Konfiguration aus. +##view_adminRoles_failLdapAvailableGroups = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. view_adminRoles_failLdapGroups = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. view_adminRoles_failLdapGroupsRole = Konnte die LDAP-Gruppen für die Rolle nicht laden. +##view_adminRoles_failLdapGroupsSettings = Konnte de LDAP-Gruppen nicht laden. Annahme ist, dass es keine gibt. view_adminRoles_failRoles = Konnte die Rollen nicht laden. view_adminRoles_globalPerms = Applikationsweite Rechte view_adminRoles_ldapGroups = LDAP-Gruppen view_adminRoles_ldapGroupsReadOnly = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapGroupsSettingsReadOnly = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapQueryPageSize = Rechte auf Ressourcen +##view_adminRoles_ldapTooManyResults = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapTookLongResults = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapTookManyPagesResults = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapWarnParsingManyPagesResults = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapWarnQueryTakingLongResults = LDAP Gruppendaten können nur gelesen werden +##view_adminRoles_ldapWarnTooManyResults = LDAP Gruppendaten können nur gelesen werden view_adminRoles_noLdap = Die LDAP-Integration ist nicht konfiguriert. Um LDAP zu konfigurieren, wechseln sie zu <a {0}>{1}</a>. ##view_adminRoles_permissions_autoselecting_configureRead_implied = Autodeselected CONFIGURE_WRITE permission, since lack of CONFIGURE_READ implies lack of it... ##view_adminRoles_permissions_autoselecting_configureWrite_implied = Autoselected CONFIGURE_READ permission, since CONFIGURE_WRITE implies it... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index f5dc83b..87b4d0c 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -138,11 +138,13 @@ common_msg_noItemsToShow = 表示する項目はありません common_msg_notYetImplemented = 実装されていません common_msg_see_more = 詳細... common_msg_step_x_of_y = ステップ {1} 中 {0} 番め +##common_msg_typeToFilterResults = 実装されていません common_severity_debug = デバッグ common_severity_error = エラー common_severity_fatal = 致命的 common_severity_info = 情報 common_severity_warn = 警告 +##common_status_attention = 成功 common_status_canceled = キャンセル common_status_deferred = 延期 common_status_failed = 失敗 @@ -199,6 +201,7 @@ common_title_group = グループ common_title_group_def_total = グループ定義の合計 common_title_group_member_health = グループメンバーの状態 common_title_groups = グループ +##common_title_groupsFound = グループ common_title_help = ヘルプ common_title_host = ホスト common_title_id = ID @@ -212,6 +215,7 @@ common_title_kind = 種類 common_title_lastUpdated = 最終更新 common_title_lastUpdatedBy = 最終更新(による) common_title_ldapGroups = LDAPグループ +##common_title_ldapGroupsAvailable = LDAPグループ common_title_mashup = マッシュアップ common_title_members_reporting = メンバーのリポート common_title_message = メッセージ @@ -236,6 +240,8 @@ common_title_platform_total = プラットフォームの合計 common_title_plugin = プラグイン common_title_port = ポート common_title_providers = プロバイダ +##common_title_queryPagesParsed = LDAPグループ +##common_title_queryProgress = LDAPグループ common_title_recent_alerts = 最近のアラート common_title_recent_bundle_deployments = 最近のバンドルのデプロイ common_title_recent_configuration_updates = 最近の構成の更新 @@ -275,6 +281,7 @@ common_title_sort_order_tooltip = 結果のソート順を設定 common_title_start = 開始 common_title_status = ステータス common_title_stop = 停止 +##common_title_suggest = サマリ common_title_summary = サマリ common_title_tag_cloud = タグクラウド common_title_timestamp = 日付/時間 @@ -500,12 +507,22 @@ view_adminRoles_assignedGroups = 割り当てられたリソースグループ view_adminRoles_assignedSubjects = 割り当てられたSubjects ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name. view_adminRoles_failLdap = LDAPが構成されたかどうかの決定に失敗しました - LDAPが無いことを仮定します +##view_adminRoles_failLdapAvailableGroups = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します view_adminRoles_failLdapGroups = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します view_adminRoles_failLdapGroupsRole = ロールのために利用可能なLDAPグループをロードするのに失敗しました +##view_adminRoles_failLdapGroupsSettings = 利用可能なLDAPグループを読み出すのに失敗しました - LDAPグループが無いことを仮定します view_adminRoles_failRoles = ロールの取り出しに失敗しました view_adminRoles_globalPerms = グローバル権限 view_adminRoles_ldapGroups = LDAPグループ view_adminRoles_ldapGroupsReadOnly = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapGroupsSettingsReadOnly = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapQueryPageSize = リソース権限 +##view_adminRoles_ldapTooManyResults = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapTookLongResults = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapTookManyPagesResults = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapWarnParsingManyPagesResults = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapWarnQueryTakingLongResults = LDAPグループデータは読み出し専用です +##view_adminRoles_ldapWarnTooManyResults = LDAPグループデータは読み出し専用です view_adminRoles_noLdap = LDAPセキュリティの統合は構成されていません。LDAPを構成するには、 <a {0}>{1}</a>に行ってください。 view_adminRoles_permissions_autoselecting_configureRead_implied = CONFIGURE_WRITE権限が自動的に選択されました。なぜなら、CONFIGURE_READが無いことがそれを暗示しているからです。 view_adminRoles_permissions_autoselecting_configureWrite_implied = CONFIGURE_READ権限が自動的に選択されました。なぜなら、CONFIGURE_WRITEがそれを暗示しているからです。 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index 7fc1609..351335d 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -132,10 +132,12 @@ common_msg_noItemsToShow = 표시할 항목이 없습니다. common_msg_notYetImplemented = 구현되지 않았습니다. common_msg_see_more = 자세히보기... common_msg_step_x_of_y = 단계 {0} 중 {1} 번째 +##common_msg_typeToFilterResults = 구현되지 않았습니다. common_severity_debug = 디버그 common_severity_error = 에러 common_severity_info = 정보 common_severity_warn = 경고 +##common_status_attention = 성공 common_status_canceled = 취소 common_status_deferred = 연기 common_status_failed = 실패 @@ -187,6 +189,7 @@ common_title_group = 그룹 common_title_group_def_total = 전체 그룹 정의 common_title_group_member_health = 그룹멤버 상태 common_title_groups = 그룹 +##common_title_groupsFound = 그룹 common_title_help = 도움말 common_title_host = 호스트 common_title_id = ID @@ -197,6 +200,7 @@ common_title_inventory = 인벤토리 common_title_inventoryStatus = 인벤토리 상태 common_title_inventorySummary = 인벤토리 요약 common_title_ldapGroups = LDAP 그룹 +##common_title_ldapGroupsAvailable = LDAP 그룹 common_title_members_reporting = 멤버 리포트 common_title_message = 메시지 common_title_metric = 측정 항목 @@ -219,6 +223,8 @@ common_title_platform_total = 전체 플랫폼 common_title_plugin = 플러그인 common_title_port = 포트 common_title_providers = 공급자 +##common_title_queryPagesParsed = LDAP 그룹 +##common_title_queryProgress = LDAP 그룹 common_title_recent_alerts = 최근 알림 common_title_recent_bundle_deployments = 최근 번들 배포 common_title_recent_drifts = 최근 드리프트 @@ -254,6 +260,7 @@ common_title_sort_order_tooltip = 결과의 정렬 순서를 설정 common_title_start = 시작 common_title_status = 상태 common_title_stop = 정지 +##common_title_suggest = 요약 common_title_summary = 요약 common_title_tag_cloud = 태그 클라우드 common_title_timestamp = 날짜/시간 @@ -451,12 +458,15 @@ view_adminRoles_assignedGroups = 할당된 자원 그룹 view_adminRoles_assignedSubjects = 할당된 Subjects view_adminRoles_failCreateRoleWithExistingName = 기존 이름 [{0}]과 역할을 만들지 못했습니다. 다른 이름을 사용하십시오. view_adminRoles_failLdap = LDAP이 설정되었는지 여부의 결정에 실패했습니다 - LDAP이 없는 것을 가정합니다. +##view_adminRoles_failLdapAvailableGroups = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. view_adminRoles_failLdapGroups = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. view_adminRoles_failLdapGroupsRole = 역할을 위해 사용가능한 LDAP 그룹을 로드하느데 실패했습니다. +##view_adminRoles_failLdapGroupsSettings = 사용가능한 LDAP 그룹을 읽는데 실패했습니다 - LDAP 그룹이 없는 것을 가정합니다. view_adminRoles_failRoles = 역할 제거에 실패했습니다. view_adminRoles_globalPerms = 글로벌 권한 view_adminRoles_ldapGroups = LDAP 그룹 ##view_adminRoles_ldapGroupsReadOnly = LDAP group data is read only +##view_adminRoles_ldapQueryPageSize = 리소스 권한 view_adminRoles_noLdap = LDAP 보안 통합이 설정되지 않았습니다. LDAP을 구성하려면 <a {0}>{1}</a>로 가십시요. ##view_adminRoles_permissions_autoselecting_configureRead_implied = Autodeselected CONFIGURE_WRITE permission, since lack of CONFIGURE_READ implies lack of it... ##view_adminRoles_permissions_autoselecting_configureWrite_implied = Autoselected CONFIGURE_READ permission, since CONFIGURE_WRITE implies it... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index 611c641..e47dc01 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -135,11 +135,13 @@ common_msg_noItemsToShow = N\u00E3o existem itens para apresentar common_msg_notYetImplemented = N\u00E3o implementado ainda common_msg_see_more = Ver detalhes... common_msg_step_x_of_y = Passo {0} de {1} +##common_msg_typeToFilterResults = N\u00E3o implementado ainda ##common_severity_debug = Debug common_severity_error = Erro ##common_severity_fatal = Fatal ##common_severity_info = Info ##common_severity_warn = Warn +##common_status_attention = Sucesso common_status_canceled = Cancelado common_status_deferred = Deferido common_status_failed = Falha @@ -191,11 +193,13 @@ common_title_edit_mode = Modo Edi\u00E7\u00E3o common_title_enabled = Habilitado? common_title_end = Fim common_title_favorites = Favoritos +##common_title_filterResultsBelow = Favoritos common_title_generalProp = Propriedades Gerais common_title_group = Grupo common_title_group_def_total = Total de Defini\u00E7\u00E3o de Grupos common_title_group_member_health = Sa\u00FAde do Membro do Grupo common_title_groups = Grupos +##common_title_groupsFound = Grupos common_title_help = Ajuda common_title_host = Host common_title_icon = \u00EDcone @@ -209,6 +213,7 @@ common_title_inventorySummary = Sum\u00E1rio do Invent\u00E1rio common_title_lastUpdated = \u00DAltima Atualiza\u00E7\u00E3o common_title_lastUpdatedBy = \u00DAltima Atualiza\u00E7\u00E3o feita por common_title_ldapGroups = Grupos LDAP +##common_title_ldapGroupsAvailable = Grupos LDAP common_title_mashup = Mashup common_title_members_reporting = Relat\u00F3rio de Membros common_title_message = Mensagem @@ -233,6 +238,8 @@ common_title_platform_total = Total de Plataformas ##common_title_plugin = Plugin common_title_port = Porta common_title_providers = Provedores +##common_title_queryPagesParsed = Grupos LDAP +##common_title_queryProgress = Grupos LDAP common_title_recent_alerts = Alertas Recentes common_title_recent_bundle_deployments = Deployments de Bundle recente common_title_recent_configuration_updates = Configura\u00E7\u00F5es Alteradas Recentemente @@ -272,6 +279,7 @@ common_title_sort_order_tooltip = Define a ordem dos resultados. common_title_start = Iniciar common_title_status = Status common_title_stop = Parar +##common_title_suggest = Sum\u00E1rio common_title_summary = Sum\u00E1rio common_title_tag_cloud = Nuvem de Tags common_title_the = O @@ -505,12 +513,22 @@ view_adminRoles_assignedGroups = Grupos de Recursos Associados view_adminRoles_assignedSubjects = Perfis Associados ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please Use another name. view_adminRoles_failLdap = Falha ao determinar se o LDAP foi configurado - assumindo como LDAP n\u00E3o configurado. +##view_adminRoles_failLdapAvailableGroups = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. view_adminRoles_failLdapGroups = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. view_adminRoles_failLdapGroupsRole = Falha ao carregar grupos do LDAP dispon\u00EDveis para o perfil. +##view_adminRoles_failLdapGroupsSettings = Falha ao recuperar os grupos dispon\u00EDveis no LDAP - assumindo como LDAP sem grupos. view_adminRoles_failRoles = Falha ao recuperar perfis. view_adminRoles_globalPerms = Permiss\u00F5es Globais view_adminRoles_ldapGroups = Grupos LDAP view_adminRoles_ldapGroupsReadOnly = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapGroupsSettingsReadOnly = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapQueryPageSize = Permiss\u00F5es do Recurso +##view_adminRoles_ldapTooManyResults = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapTookLongResults = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapTookManyPagesResults = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapWarnParsingManyPagesResults = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapWarnQueryTakingLongResults = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura +##view_adminRoles_ldapWarnTooManyResults = Informa\u00E7\u00F5es do grupo LDAP com permiss\u00F5es apenas de leitura view_adminRoles_noLdap = A integra\u00E7\u00E3o com o LDAP ainda n\u00E3o foi configurada. Para configurar o LDAP acesse <a {0}>{1}</a>. view_adminRoles_permissions_autoselecting_configureRead_implied = Permiss\u00E3o CONFIGURE_WRITE desmarcada automaticamente devida a aus\u00EAncia da permiss\u00E3o CONFIGURE_READ... view_adminRoles_permissions_autoselecting_configureWrite_implied = Permiss\u00E3o CONFIGURE_READ marcada automaticamente devida a marca\u00E7\u00E3o de CONFIGURE_WRITE... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index bae4916..4004a35 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2252,11 +2252,13 @@ common_msg_noItemsToShow = Отсутствуют элементы для ото common_msg_notYetImplemented = Еще не реализовано common_msg_see_more = подробнее... common_msg_step_x_of_y = Шаг {0} из {1} +##common_msg_typeToFilterResults = Еще не реализовано common_severity_debug = Отладка common_severity_error = Ошибка common_severity_fatal = Фатальный common_severity_info = Информация common_severity_warn = Предупреждение +##common_status_attention = Успешный common_status_canceled = Отменён common_status_deferred = Отложенный common_status_failed = Безуспешно @@ -2312,6 +2314,7 @@ common_title_group = Группа common_title_group_def_total = Определение количества групп common_title_group_member_health = Состояние члена группы common_title_groups = Группы +##common_title_groupsFound = Группы common_title_help = Помощь common_title_host = Host common_title_id = ID @@ -2323,6 +2326,7 @@ common_title_inventorySummary = Итог инвентаризации common_title_lastUpdated = Последнее обновление common_title_lastUpdatedBy = Последнее обновление от common_title_ldapGroups = LDAP-группы +##common_title_ldapGroupsAvailable = LDAP-группы common_title_mashup = Mashup common_title_members_reporting = Количество пользователей отчетности common_title_message = Сообщение @@ -2346,6 +2350,8 @@ common_title_platform_total = Количество платформ common_title_plugin = Плагин common_title_port = Порт common_title_providers = Провайдеры +##common_title_queryPagesParsed = LDAP-группы +##common_title_queryProgress = LDAP-группы common_title_recent_alerts = Последние предупреждения common_title_recent_bundle_deployments = Последние развертывания пакета common_title_recent_configuration_updates = Последние обновления конфигурации @@ -2382,6 +2388,7 @@ common_title_sort_order_tooltip = Установить порядок сорти common_title_start = Старт common_title_status = Статус common_title_stop = Стоп +##common_title_suggest = Сводка common_title_summary = Сводка common_title_tag_cloud = Облако тегов common_title_timestamp = Дата/Времяcommon_title_total=Итог @@ -2587,13 +2594,23 @@ view_adminRoles_assignedGroups = Назначенные группы ресур view_adminRoles_assignedSubjects = Назначенные субъекты ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please use another name. view_adminRoles_failLdap = Не удалось определить, настроен ли LDAP - предположительно LDAP отсутствует. +##view_adminRoles_failLdapAvailableGroups = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют view_adminRoles_failLdapGroups = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют view_adminRoles_failLdapGroupsRole = Не удалось загрузить LDAP группы, доступные для роли. +##view_adminRoles_failLdapGroupsSettings = Не удалось получить LDAP-группы. Предположительно LDAP группы отсутствуют view_adminRoles_failRoles = Не удалось получить роли. view_adminRoles_globalPerms = Глобальные полномочия view_adminRoles_ldapGroups = LDAP-группы view_adminRoles_ldapGroupsReadOnly = данные LDAP групп доступны только для чтения ##view_adminRoles_noLdap = The LDAP security integration is not configured. To configure LDAP, go to <a {0}>{1}</a>. +##view_adminRoles_ldapGroupsSettingsReadOnly = данные LDAP групп доступны только для чтения +##view_adminRoles_ldapQueryPageSize = Полномочия ресурса +##view_adminRoles_ldapTooManyResults = данные LDAP групп доступны только для чтения +##view_adminRoles_ldapTookLongResults = данные LDAP групп доступны только для чтения +##view_adminRoles_ldapTookManyPagesResults = данные LDAP групп доступны только для чтения +##view_adminRoles_ldapWarnParsingManyPagesResults = данные LDAP групп доступны только для чтения +##view_adminRoles_ldapWarnQueryTakingLongResults = данные LDAP групп доступны только для чтения +##view_adminRoles_ldapWarnTooManyResults = данные LDAP групп доступны только для чтения view_adminRoles_permissions_autoselecting_configureRead_implied = Автоматически отключено CONFIGURE_WRITE полномочие, поскольку отсутствует CONFIGURE_READ... view_adminRoles_permissions_autoselecting_configureWrite_implied = Автоматически выбрано CONFIGURE_READ полномочие, поскольку CONFIGURE_WRITE подразумевает, что ... ##view_adminRoles_permissions_autoselecting_manageBundleGroups_implied = Autoselected View Bundles, which is granted by Manage Bundle Groups... diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index 2bcd8fc..1364008 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -135,11 +135,13 @@ common_msg_noItemsToShow = \u6ca1\u6709\u6761\u76ee\u663e\u793a common_msg_notYetImplemented = \u5c1a\u672a\u5b9e\u73b0 common_msg_see_more = \u67e5\u770b\u66f4\u591a... common_msg_step_x_of_y = Step {0} of {1} +##common_msg_typeToFilterResults = \u5c1a\u672a\u5b9e\u73b0 common_severity_debug = \u8c03\u8bd5 common_severity_error = Error common_severity_fatal = \u4e25\u91cd common_severity_info = \u4fe1\u606f common_severity_warn = \u8b66\u544a +##common_status_attention = \u6210\u529f common_status_canceled = \u53d6\u6d88 common_status_deferred = \u5ef6\u671f common_status_failed = \u5931\u8d25 @@ -195,6 +197,7 @@ common_title_group = \u7ec4 common_title_group_def_total = \u5b9a\u4e49\u7ec4\u603b\u6570 common_title_group_member_health = \u7ec4\u5458\u5065\u5eb7\u5ea6 common_title_groups = \u7ec4 +##common_title_groupsFound = \u7ec4 common_title_help = \u5e2e\u52a9 common_title_host = \u4e3b\u673a common_title_id = ID @@ -206,6 +209,7 @@ common_title_inventorySummary = \u6e05\u5355\u6c47\u603b common_title_lastUpdated = \u6700\u8fd1\u66f4\u65b0 common_title_lastUpdatedBy = \u6700\u8fd1\u66f4\u65b0\u8005 common_title_ldapGroups = LDAP\u7ec4 +##common_title_ldapGroupsAvailable = LDAP\u7ec4 common_title_mashup = Mashup common_title_members_reporting = \u7ec4\u62a5\u8868 common_title_message = \u6d88\u606f @@ -230,6 +234,8 @@ common_title_platform_total = \u6240\u6709\u5e73\u53f0 common_title_plugin = \u63d2\u4ef6 common_title_port = \u7aef\u53e3 common_title_providers = \u63d0\u4f9b\u8005 +##common_title_queryPagesParsed = LDAP\u7ec4 +##common_title_queryProgress = LDAP\u7ec4 common_title_recent_alerts = \u6700\u8fd1\u544a\u8b66 common_title_recent_bundle_deployments = \u6700\u8fd1\u53d1\u5e03Bundles common_title_recent_configuration_updates = \u6700\u8fd1\u914d\u7f6e\u66f4\u65b0 @@ -269,6 +275,7 @@ common_title_sort_order_tooltip = \u8bbe\u7f6e\u6392\u5e8f\u65b9\u5f0f. common_title_start = \u5f00\u59cb common_title_status = \u72b6\u6001 common_title_stop = \u505c\u6b62 +##common_title_suggest = \u7edf\u8ba1 common_title_summary = \u7edf\u8ba1 common_title_tag_cloud = \u6807\u7b7e\u4e91 common_title_the = The @@ -494,12 +501,22 @@ view_adminRoles_assignedGroups = \u5206\u914d\u7684\u8d44\u6e90\u7ec4 view_adminRoles_assignedSubjects = \u5206\u914d\u7684\u4e3b\u9898 ##view_adminRoles_failCreateRoleWithExistingName = Failed to create role with existing name [{0}]. Please Use another name. view_adminRoles_failLdap = \u65e0\u6cd5\u786e\u5b9aLDAP - \u5047\u5b9a\u6ca1\u6709LDAP. +##view_adminRoles_failLdapAvailableGroups = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. view_adminRoles_failLdapGroups = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. view_adminRoles_failLdapGroupsRole = \u52a0\u8f7dLDAP\u7ec4\u89d2\u8272\u5931\u8d25. +##view_adminRoles_failLdapGroupsSettings = \u67e5\u8be2\u6709\u6548LDAP\u7ec4\u5931\u8d25 - \u5047\u5b9a\u65e0DAP\u7ec4. view_adminRoles_failRoles = \u53d6\u5f97\u89d2\u8272\u5931\u8d25. view_adminRoles_globalPerms = \u5168\u5c40\u6388\u6743 view_adminRoles_ldapGroups = LDAP\u7ec4 view_adminRoles_ldapGroupsReadOnly = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapGroupsSettingsReadOnly = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapQueryPageSize = \u8d44\u6e90\u6388\u6743 +##view_adminRoles_ldapTooManyResults = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapTookLongResults = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapTookManyPagesResults = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapWarnParsingManyPagesResults = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapWarnQueryTakingLongResults = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb +##view_adminRoles_ldapWarnTooManyResults = LDAP\u7ec4\u6570\u636e\u4e3a\u53ea\u8bfb view_adminRoles_noLdap = \u6ca1\u6709\u96c6\u6210LDAP\u5b89\u5168, \u5230<a {0}>{1}</a>. ##view_adminRoles_permissions_autoselecting_configureRead_implied = Autodeselected CONFIGURE_WRITE permission, since lack of CONFIGURE_READ implies lack of it... ##view_adminRoles_permissions_autoselecting_configureWrite_implied = Autoselected CONFIGURE_READ permission, since CONFIGURE_WRITE implies it...
commit fba939e0ac8ea38be1e62e0049cbf2d2eb760215 Author: Simeon Pinder spinder@fulliautomatix.conchfritter.com Date: Fri Aug 9 10:22:37 2013 -0400
[BZ 990576] - insert hard ldap group limit with parsing to guard against excessive ui perf issues. - fix ldap search filter issue - add Suggest/Advice component for more feedback for ldap integration. - disable edit on Suggest/Advice component - clean up selector feedback ui threads to guard against refresh. - refresh cached ldap results after 30 mins. - modify AbstractSelector to better support overriding the availableFilterForm
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java index b17961d..8d53b82 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java @@ -36,11 +36,18 @@ import com.smartgwt.client.data.Record; import com.smartgwt.client.data.fields.DataSourceTextField; import com.smartgwt.client.types.TitleOrientation; import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.events.ItemChangedEvent; +import com.smartgwt.client.widgets.form.events.ItemChangedHandler; import com.smartgwt.client.widgets.form.fields.CheckboxItem; import com.smartgwt.client.widgets.form.fields.FormItemIcon; import com.smartgwt.client.widgets.form.fields.SpacerItem; import com.smartgwt.client.widgets.form.fields.StaticTextItem; +import com.smartgwt.client.widgets.form.fields.TextAreaItem; import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.form.fields.events.ChangeEvent; +import com.smartgwt.client.widgets.form.fields.events.ChangeHandler; +import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; +import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.layout.HLayout;
@@ -63,7 +70,9 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c public static final String FIELD_ID = "id"; public static final String FIELD_NAME = "name"; public static final String FIELD_DESCRIPTION = "description"; - private static boolean queryCompleted = false; + final TextItem searchTextItem = new TextItem(); + protected int cursorPosition; + private static int retryAttempt = 0;
//override the selector key for ldap group selection. protected String getSelectorKey() { @@ -86,7 +95,7 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c availableFilterForm.setNumCols(2); } int groupPanelWidth = 375; - int groupPanelHeight = 140; + int groupPanelHeight = 150;
// final TextItem search = new TextItem("search", // MSG.common_title_search()); @@ -100,6 +109,25 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c availableGroupDetails.setGroupTitle("Available Groups Results"); availableGroupDetails.setIsGroup(true); availableGroupDetails.setWrapItemTitles(false); + //add itemChanged handler to listen for changes to SearchItem + availableGroupDetails.addItemChangedHandler(new ItemChangedHandler() { + public void onItemChanged(ItemChangedEvent itemChangedEvent) { + + latestCriteria = getLatestCriteria(null); + + Timer timer = new Timer() { + @Override + public void run() { + if (latestCriteria != null) { + Criteria criteria = latestCriteria; + latestCriteria = null; + populateAvailableGrid(criteria); + } + } + }; + timer.schedule(500); + } + }); } final TextItem resultCountItem = new TextItem("resultCount", "Groups Found"); { @@ -111,23 +139,49 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c pageCountItem.setCanEdit(false); pageCountItem.setWidth("100%"); } + final TextAreaItem adviceItem = new TextAreaItem("advice", "Suggest"); + { + adviceItem.setWidth("100%"); + adviceItem.setHeight(20); + String feedback = "(None)"; + adviceItem.setValue(feedback); + adviceItem.setTooltip(feedback); + adviceItem.setDisabled(true); + adviceItem.addChangeHandler(new ChangeHandler() { + @Override + public void onChange(ChangeEvent event) { + event.cancel(); + cursorPosition = adviceItem.getSelectionRange()[0]; + } + }); + adviceItem.addChangedHandler(new ChangedHandler() { + + @Override + public void onChanged(ChangedEvent event) { + adviceItem.setSelectionRange(cursorPosition, cursorPosition); + } + }); + } // final TextItem search = new TextItem("search", // MSG.common_title_search()); - final TextItem search = new TextItem("search", "Search[within results]"); { - search.setWidth("100%"); - search.setTooltip("Start typing here to show groups containing the typed characters."); + searchTextItem.setName("search"); + searchTextItem.setTitle("Filter[results below]"); + searchTextItem.setWidth("100%"); + searchTextItem.setTooltip("Start typing here to only show groups containing the typed characters."); } final FormItemIcon loadingIcon = new FormItemIcon(); final FormItemIcon successIcon = new FormItemIcon(); final FormItemIcon failIcon = new FormItemIcon(); + final FormItemIcon attentionIcon = new FormItemIcon(); String successIconPath = "[SKIN]/actions/ok.png"; String failedIconPath = "[SKIN]/actions/exclamation.png"; String loadingIconPath = "[SKIN]/loading.gif"; - //icon.setSrc("[SKIN]/actions/help.png"); + String attentionIconPath = "[SKIN]/Dialog/warn.png"; loadingIcon.setSrc(loadingIconPath); successIcon.setSrc(successIconPath); failIcon.setSrc(failedIconPath); + attentionIcon.setSrc(attentionIconPath);
final StaticTextItem groupQueryStatus = new StaticTextItem(); { @@ -136,7 +190,7 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c groupQueryStatus.setDefaultValue("Loading..."); groupQueryStatus.setIcons(loadingIcon); } - availableGroupDetails.setItems(resultCountItem, pageCountItem, groupQueryStatus, new SpacerItem(), search); + availableGroupDetails.setItems(resultCountItem, pageCountItem, groupQueryStatus, adviceItem, searchTextItem);
// Ldap Group Settings region final DynamicForm ldapGroupSettings = new DynamicForm(); @@ -182,8 +236,8 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c //You have to set this attribute groupUsePosixGroupsItem.setAttribute("labelAsTitle", true); } - ldapGroupSettings - .setItems(groupSearch, groupMember, groupQueryPagingItem, groupQueryPagingCountItem, groupUsePosixGroupsItem); + ldapGroupSettings.setItems(groupSearch, groupMember, groupQueryPagingItem, groupQueryPagingCountItem, + groupUsePosixGroupsItem);
// orient both panels next to each other HLayout panel = new HLayout(); @@ -196,6 +250,8 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c } availableFilterForm.addChild(panel);
+ final long ldapGroupSelectorRequestId = System.currentTimeMillis(); + //launch operations to populate/refresh LDAP Group Query contents. final Timer ldapPropertiesTimer = new Timer() { public void run() { @@ -230,75 +286,119 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c } } }; - ldapPropertiesTimer.scheduleRepeating(2000); // repeat interval in milliseconds, e.g. 30000 = 30seconds + ldapPropertiesTimer.schedule(2000); // repeat interval in milliseconds, e.g. 30000 = 30seconds
//launch operations to populate/refresh LDAP Group Query contents. final Timer availableGroupsTimer = new Timer() { public void run() { - if (!queryCompleted) { - //make request to RHQ about state of latest LDAP GWT request - GWTServiceLookup.getLdapService().findAvailableGroupsStatus( - new AsyncCallback<Set<Map<String, String>>>() { - @Override - public void onFailure(Throwable caught) { - groupQueryStatus.setIcons(failIcon); - groupQueryStatus - .setDefaultValue("Fail: Unable to retrieve status for latest AvailableGroups() call."); - //TODO: update this message - CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); + final String attention = "Attention"; + final String success = "Success"; + final String none = "(None)"; + final String failed = "Failed"; + //make request to RHQ about state of latest LDAP GWT request + GWTServiceLookup.getLdapService().findAvailableGroupsStatus( + new AsyncCallback<Set<Map<String, String>>>() { + @Override + public void onFailure(Throwable caught) { + groupQueryStatus.setIcons(failIcon); + groupQueryStatus.setDefaultValue(failed); + String adviceValue = "Failed: Unable to retrieve status for latest AvailableGroups() call."; + adviceItem.setValue(adviceValue); + adviceItem.setTooltip(adviceValue); + //TODO: update this message + CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); + retryAttempt++; + if (retryAttempt > 3) { + cancel();//kill thread + retryAttempt = 0; } + }
- @Override - public void onSuccess(Set<Map<String, String>> results) { - // Log.debug("@@@@@@@ findAvailableGroupsStatus: SUCCESS:" + System.currentTimeMillis() - // + ":count:" - // + results.size()); - long start = -1, end = -1; - int pageCount = 0; - int resultCountValue = 0; - for (Map<String, String> map : results) { - String key = map.keySet().toArray()[0] + ""; - if (key.equals("query.results.parsed")) { - String value = map.get(key); - resultCountItem.setValue(value); - resultCountValue = Integer.valueOf(value); - } else if (key.equals("query.complete")) { - String value = map.get(key); - queryCompleted = Boolean.valueOf(value); - } else if (key.equals("query.start.time")) { - String value = map.get(key); - start = Long.valueOf(value); - } else if (key.equals("query.end.time")) { - String value = map.get(key); - end = Long.valueOf(value); - } else if (key.equals("query.page.count")) { - String value = map.get(key); - pageCountItem.setValue(value); - pageCount = Integer.valueOf(value); - } + @Override + public void onSuccess(Set<Map<String, String>> results) { + long start = -1, current = -1; + int pageCount = 0; + int resultCountValue = 0; + boolean queryCompleted = false; + for (Map<String, String> map : results) { + String key = map.keySet().toArray()[0] + ""; + if (key.equals("query.results.parsed")) { + String value = map.get(key); + resultCountItem.setValue(value); + resultCountValue = Integer.valueOf(value); + } else if (key.equals("query.complete")) { + String value = map.get(key); + queryCompleted = Boolean.valueOf(value); + } else if (key.equals("query.start.time")) { + String value = map.get(key); + start = Long.valueOf(value); + } else if (key.equals("query.current.time")) { + String value = map.get(key); + current = Long.valueOf(value); + } else if (key.equals("query.page.count")) { + String value = map.get(key); + pageCountItem.setValue(value); + pageCount = Integer.valueOf(value); } - //act on status details to add extra perf suggestions - if (queryCompleted) { + } + //Update status information + String warnTooManyResults = " A lot of results are being returned. Modify your 'Group Search Filter' to return fewer results."; + String warnQueryTakingLongResults = " Query taking a while to complete. Modify your 'Group Search Filter' to return fewer results."; + String warnParsingManyPagesResults = " Query requires a lot of pages. Modify your 'Group Search Page Size' to return more results per request."; + boolean resultCountWarning = false; + boolean pageCountWarning = false; + boolean timePassingWarning = false; + if ((resultCountWarning = (resultCountValue > 5000)) + || (pageCountWarning = (pageCount > 5)) + || (timePassingWarning = (current - start) > 5 * 1000)) { + adviceItem.setDisabled(false); + groupQueryStatus.setIcons(attentionIcon); + if (resultCountWarning) { + adviceItem.setValue(warnTooManyResults); + adviceItem.setTooltip(warnTooManyResults); + } else if (pageCountWarning) { + adviceItem.setValue(warnParsingManyPagesResults); + adviceItem.setTooltip(warnParsingManyPagesResults); + } else if (timePassingWarning) { + adviceItem.setValue(warnQueryTakingLongResults); + adviceItem.setTooltip(warnQueryTakingLongResults); + } + } + + //act on status details to add extra perf suggestions. Kill threads older than 30 mins + long parseTime = System.currentTimeMillis() - ldapGroupSelectorRequestId; + if ((queryCompleted) || (parseTime) > 30 * 60 * 1000) { + String tooManyResults = "Too many results to show all. Modify your 'Group Search Filter' to return fewer than 20000 results."; + String queryTookLongResults = " Query took " + parseTime + + " ms to complete. Modify your 'Group Search Filter' to return fewer results."; + String queryTookManyPagesResults = " Query required " + + pageCount + + " pages to complete. Modify 'Group Search Page Size' to return more results per request."; + adviceItem.setDisabled(false); + groupQueryStatus.setIcons(attentionIcon); + groupQueryStatus.setDefaultValue(attention); + if (resultCountValue > 20000) {//results throttled + adviceItem.setValue(tooManyResults); + adviceItem.setTooltip(tooManyResults); + } else if ((current - start) >= 10 * 1000) {// took longer than 10s + adviceItem.setValue(queryTookLongResults); + adviceItem.setTooltip(queryTookLongResults); + } else if (pageCount >= 20) {// required more than 20 pages of results + adviceItem.setValue(queryTookManyPagesResults); + adviceItem.setTooltip(queryTookManyPagesResults); + } else {//simple success. + groupQueryStatus.setDefaultValue(success); groupQueryStatus.setIcons(successIcon); - String success = "Success"; - String tooManyResults = success + ": Too many results."; - String queryTookLongResults = success + ": Query took long to complete."; - String queryTookManyPagesResults = success + ": Query required a lot of paging."; - //TODO: add in extra information about results. - if (resultCountValue > 20000) {//results throttled - groupQueryStatus.setDefaultValue(tooManyResults); - } else if ((end - start) >= 10 * 1000) {// took longer than 10s - groupQueryStatus.setDefaultValue(queryTookLongResults); - } else if (pageCount >= 20) {// took longer than 10s - groupQueryStatus.setDefaultValue(queryTookManyPagesResults); - } + adviceItem.setValue(none); + adviceItem.setTooltip(none); + adviceItem.setDisabled(true); } - availableGroupDetails.markForRedraw(); //now cancel the timer cancel(); } - }); - } + availableGroupDetails.markForRedraw(); + } + }); } }; availableGroupsTimer.scheduleRepeating(3000); // repeat interval in milliseconds, e.g. 30000 = 30seconds @@ -315,7 +415,9 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c */ @Override protected Criteria getLatestCriteria(DynamicForm availableFilterForm) { - String search = (String) availableFilterForm.getValue("search"); + //String search = (String) availableFilterForm.getValue("search"); + //non-trivial recursive form items possible. Retrieve from correct form item. + String search = searchTextItem.getValueAsString(); Criteria criteria = new Criteria(); if (null != search) { criteria.addCriteria("name", search); @@ -330,9 +432,10 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c
public static class LdapGroupsDataSource extends RPCDataSource<LdapGroup, org.rhq.core.domain.criteria.Criteria> {
- //cache ldap group data from external server + //cache ldap group data from external server for 30 mins then stale. private Set<Map<String, String>> cachedLdapGroupsAvailable; private Map<String, Map<String, String>> cachedNameKeyedMap; + private long cachedLdapGroupsLast = -1;
public LdapGroupsDataSource() { DataSourceTextField nameField = new DataSourceTextField(FIELD_NAME, FIELD_NAME); @@ -368,8 +471,9 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c @Override protected void executeFetch(final DSRequest request, final DSResponse response, final org.rhq.core.domain.criteria.Criteria unused) { - //if not null then go through to initialize - if (cachedLdapGroupsAvailable == null) { + //if not null or stale then go through to initialize|reset + if ((cachedLdapGroupsAvailable == null) + || ((System.currentTimeMillis() - cachedLdapGroupsLast) > 30 * 60 * 1000)) { fetchLdapGroupsFromServerAsync(request, response); } else {//use cached data and return correct response //process cachedLdapGroupsAvailable based on criteria @@ -422,6 +526,7 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c public void onSuccess(Set<Map<String, String>> locatedGroupMaps) { Log.debug("Successfully located " + locatedGroupMaps.size() + " available LDAP groups."); cachedLdapGroupsAvailable = locatedGroupMaps; + cachedLdapGroupsLast = System.currentTimeMillis(); //all groups displayed initially PageList<LdapGroup> ldapGroups = convertToPageList(locatedGroupMaps); sendSuccessResponse(request, response, ldapGroups); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/selector/AbstractSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/selector/AbstractSelector.java index 12c5eb0..6f09142 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/selector/AbstractSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/selector/AbstractSelector.java @@ -65,9 +65,9 @@ import com.smartgwt.client.widgets.layout.VStack;
import org.rhq.enterprise.gui.coregui.client.ImageManager; import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedUtility; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVStack; -import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedUtility;
/** * @author Greg Hinkle @@ -344,7 +344,7 @@ public abstract class AbstractSelector<T, C extends org.rhq.core.domain.criteria return availableSectionStack; }
- private void populateAvailableGrid(Criteria criteria) { + protected void populateAvailableGrid(Criteria criteria) { // TODO until http://code.google.com/p/smartgwt/issues/detail?id=490 is fixed always go to the server for data this.datasource.invalidateCache(); DSRequest requestProperties = new DSRequest(); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java index 67abb77..dc53a3c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java @@ -96,14 +96,15 @@ public class LdapGroupManagerBean implements LdapGroupManagerLocal { private static boolean groupQueryComplete = false; private static int groupQueryResultCount = 0; private static long groupQueryStartTime = -1; - private static long groupQueryEndTime = -1; + private static long groupQueryCurrentTime = -1; private static int groupQueryPageCount = 0; + private static final int LDAP_GROUP_QUERY_LIMIT = 20000;//start to see a lot of ui responsiveness issues beyond this.
private void resetGroupQueryDetails() { groupQueryComplete = false; groupQueryResultCount = 0; groupQueryStartTime = -1; - groupQueryEndTime = -1; + groupQueryCurrentTime = -1; groupQueryPageCount = 0; } public Set<Map<String, String>> findAvailableGroups() { @@ -138,8 +139,8 @@ public class LdapGroupManagerBean implements LdapGroupManagerLocal { availableGroupsQueryStatus.add(buildStatusEntry("query.results.parsed", String.valueOf(groupQueryResultCount))); //query.start.time => timestamp availableGroupsQueryStatus.add(buildStatusEntry("query.start.time", String.valueOf(groupQueryStartTime))); - //query.end.time => timestamp|-1 - availableGroupsQueryStatus.add(buildStatusEntry("query.end.time", String.valueOf(groupQueryEndTime))); + //query.current.time => timestamp|-1 + availableGroupsQueryStatus.add(buildStatusEntry("query.current.time", String.valueOf(groupQueryCurrentTime))); //query.page.count => 0...N availableGroupsQueryStatus.add(buildStatusEntry("query.page.count", String.valueOf(groupQueryPageCount)));
@@ -470,8 +471,11 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" int passedInPageSize = -1; try { passedInPageSize = Integer.valueOf(groupPageSize.trim()); - if (passedInPageSize > 0) { + if ((passedInPageSize > 0) && (passedInPageSize <= LDAP_GROUP_QUERY_LIMIT)) { defaultPageSize = passedInPageSize; + } else {//keep defaults and log actual value being used. + log.debug("LDAP Group Page Size passed '" + groupPageSize + + "' was ignored. Defaulting to 1000."); } } catch (NumberFormatException nfe) { //log issue and do nothing. Go with the default. @@ -494,6 +498,7 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), ""
//update queryResultCount groupQueryResultCount = groupDetailsMap.size(); + groupQueryCurrentTime = System.currentTimeMillis();
// continually parsing pages of results until we're done. // only if they're enabled in the UI. @@ -511,7 +516,7 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" } } //continually parsing pages of results until we're done. - while (cookie != null) { + while ((groupQueryResultCount <= LDAP_GROUP_QUERY_LIMIT) && (cookie != null)) { //ensure the next requests contains the session/cookie details ctx.setRequestControls(new Control[] { new PagedResultsControl(defaultPageSize, cookie, Control.CRITICAL) }); @@ -520,19 +525,21 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" //update Query state after each page groupQueryResultCount = groupDetailsMap.size(); groupQueryPageCount++; + groupQueryCurrentTime = System.currentTimeMillis();
//empty out cookie cookie = null; - //test for further iterations - controls = ctx.getResponseControls(); - if (controls != null) { - for (Control control : controls) { - if (control instanceof PagedResultsResponseControl) { - PagedResultsResponseControl pagedResult = (PagedResultsResponseControl) control; - cookie = pagedResult.getCookie(); + //insert group query throttle. + //test for further iterations + controls = ctx.getResponseControls(); + if (controls != null) { + for (Control control : controls) { + if (control instanceof PagedResultsResponseControl) { + PagedResultsResponseControl pagedResult = (PagedResultsResponseControl) control; + cookie = pagedResult.getCookie(); + } } } - } } } } @@ -553,7 +560,7 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" throw new LdapCommunicationException(iex); } //update end of query information - groupQueryEndTime = System.currentTimeMillis(); + groupQueryCurrentTime = System.currentTimeMillis(); groupQueryComplete = true; return groupDetailsMap; } @@ -575,7 +582,9 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" //execute search based on controls and context passed in. NamingEnumeration<SearchResult> answer = ctx.search(baseDNs[x], filter, searchControls); boolean ldapApiEnumerationBugEncountered = false; - while ((!ldapApiEnumerationBugEncountered) && answer.hasMoreElements()) {//BZ:582471- ldap api bug change + int resultCount = 0; + while ((resultCount <= LDAP_GROUP_QUERY_LIMIT) && (groupDetailsMap.size() <= LDAP_GROUP_QUERY_LIMIT) + && (!ldapApiEnumerationBugEncountered) && answer.hasMoreElements()) {//BZ:582471- ldap api bug change // We use the first match SearchResult si = null; try { @@ -595,6 +604,7 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" entry.put("name", name); entry.put("description", description); groupDetailsMap.add(entry); + resultCount++; } }
commit d4514acdcfd28346cddcb8660a9d89ef52cf65b9 Author: Simeon Pinder spinder@fulliautomatix.conchfritter.com Date: Tue Aug 6 14:36:55 2013 -0400
[BZ 990576] Add messaging and updates around ldap query performance for adminstrator.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java index 4f763ff..b17961d 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/roles/RoleLdapGroupSelector.java @@ -27,17 +27,25 @@ import java.util.HashSet; import java.util.Map; import java.util.Set;
+import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Criteria; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; import com.smartgwt.client.data.Record; import com.smartgwt.client.data.fields.DataSourceTextField; +import com.smartgwt.client.types.TitleOrientation; import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.CheckboxItem; +import com.smartgwt.client.widgets.form.fields.FormItemIcon; import com.smartgwt.client.widgets.form.fields.SpacerItem; +import com.smartgwt.client.widgets.form.fields.StaticTextItem; import com.smartgwt.client.widgets.form.fields.TextItem; import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.layout.HLayout;
+import org.rhq.core.domain.common.composite.SystemSetting; +import org.rhq.core.domain.common.composite.SystemSettings; import org.rhq.core.domain.resource.group.LdapGroup; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; @@ -55,6 +63,7 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c public static final String FIELD_ID = "id"; public static final String FIELD_NAME = "name"; public static final String FIELD_DESCRIPTION = "description"; + private static boolean queryCompleted = false;
//override the selector key for ldap group selection. protected String getSelectorKey() { @@ -72,11 +81,227 @@ public class RoleLdapGroupSelector extends AbstractSelector<LdapGroup, org.rhq.c @Override protected DynamicForm getAvailableFilterForm() { DynamicForm availableFilterForm = new DynamicForm(); - availableFilterForm.setWidth100(); - availableFilterForm.setNumCols(2); - - final TextItem search = new TextItem("search", MSG.common_title_search()); - availableFilterForm.setItems(search, new SpacerItem()); + { + availableFilterForm.setWidth100(); + availableFilterForm.setNumCols(2); + } + int groupPanelWidth = 375; + int groupPanelHeight = 140; + + // final TextItem search = new TextItem("search", + // MSG.common_title_search()); + + // Structure the display area into two separate display regions + // Available Groups region + final DynamicForm availableGroupDetails = new DynamicForm(); + { + availableGroupDetails.setWidth(groupPanelWidth); + availableGroupDetails.setHeight(groupPanelHeight); + availableGroupDetails.setGroupTitle("Available Groups Results"); + availableGroupDetails.setIsGroup(true); + availableGroupDetails.setWrapItemTitles(false); + } + final TextItem resultCountItem = new TextItem("resultCount", "Groups Found"); + { + resultCountItem.setCanEdit(false); + resultCountItem.setWidth("100%"); + } + final TextItem pageCountItem = new TextItem("pageCount", "Query Pages Parsed"); + { + pageCountItem.setCanEdit(false); + pageCountItem.setWidth("100%"); + } + // final TextItem search = new TextItem("search", + // MSG.common_title_search()); + final TextItem search = new TextItem("search", "Search[within results]"); + { + search.setWidth("100%"); + search.setTooltip("Start typing here to show groups containing the typed characters."); + } + final FormItemIcon loadingIcon = new FormItemIcon(); + final FormItemIcon successIcon = new FormItemIcon(); + final FormItemIcon failIcon = new FormItemIcon(); + String successIconPath = "[SKIN]/actions/ok.png"; + String failedIconPath = "[SKIN]/actions/exclamation.png"; + String loadingIconPath = "[SKIN]/loading.gif"; + //icon.setSrc("[SKIN]/actions/help.png"); + loadingIcon.setSrc(loadingIconPath); + successIcon.setSrc(successIconPath); + failIcon.setSrc(failedIconPath); + + final StaticTextItem groupQueryStatus = new StaticTextItem(); + { + groupQueryStatus.setName("groupQueryStatus"); + groupQueryStatus.setTitle("Query Progress"); + groupQueryStatus.setDefaultValue("Loading..."); + groupQueryStatus.setIcons(loadingIcon); + } + availableGroupDetails.setItems(resultCountItem, pageCountItem, groupQueryStatus, new SpacerItem(), search); + + // Ldap Group Settings region + final DynamicForm ldapGroupSettings = new DynamicForm(); + { + ldapGroupSettings.setWidth(groupPanelWidth); + ldapGroupSettings.setHeight(groupPanelHeight); + ldapGroupSettings.setGroupTitle("[Read Only] Ldap Group Settings. Edit in 'System Settings'"); + ldapGroupSettings.setIsGroup(true); + ldapGroupSettings.setWrapItemTitles(false); + } + final TextItem groupSearch = new TextItem("groupSearch", "Search Filter"); + { + groupSearch.setCanEdit(false); + groupSearch.setWidth("100%"); + } + final TextItem groupMember = new TextItem("groupMember", "Member Filter"); + { + groupMember.setCanEdit(false); + groupMember.setWidth("100%"); + } + final CheckboxItem groupQueryPagingItem = new CheckboxItem("groupQueryEnable", "Query Paging Enabled"); + { + groupQueryPagingItem.setCanEdit(false); + groupQueryPagingItem.setValue(false); + groupQueryPagingItem.setShowLabel(false); + groupQueryPagingItem.setShowTitle(true); + groupQueryPagingItem.setTitleOrientation(TitleOrientation.LEFT); + //You have to set this attribute + groupQueryPagingItem.setAttribute("labelAsTitle", true); + } + final TextItem groupQueryPagingCountItem = new TextItem("groupQueryCount", "Query Page Size"); + { + groupQueryPagingCountItem.setCanEdit(false); + groupQueryPagingCountItem.setWidth("100%"); + } + final CheckboxItem groupUsePosixGroupsItem = new CheckboxItem("groupUsePosixGroups", "Use Posix Enabled"); + { + groupUsePosixGroupsItem.setCanEdit(false); + groupUsePosixGroupsItem.setValue(false); + groupUsePosixGroupsItem.setShowLabel(false); + groupUsePosixGroupsItem.setShowTitle(true); + groupUsePosixGroupsItem.setTitleOrientation(TitleOrientation.LEFT); + //You have to set this attribute + groupUsePosixGroupsItem.setAttribute("labelAsTitle", true); + } + ldapGroupSettings + .setItems(groupSearch, groupMember, groupQueryPagingItem, groupQueryPagingCountItem, groupUsePosixGroupsItem); + + // orient both panels next to each other + HLayout panel = new HLayout(); + { + panel.addMember(availableGroupDetails); + DynamicForm spacerWrapper = new DynamicForm(); + spacerWrapper.setItems(new SpacerItem()); + panel.addMember(spacerWrapper); + panel.addMember(ldapGroupSettings); + } + availableFilterForm.addChild(panel); + + //launch operations to populate/refresh LDAP Group Query contents. + final Timer ldapPropertiesTimer = new Timer() { + public void run() { + //if system properties not set, launch request/update + String ldapGroupQuery = groupSearch.getValueAsString(); + if ((ldapGroupQuery == null) || (ldapGroupQuery.trim().isEmpty())) { + GWTServiceLookup.getSystemService().getSystemSettings(new AsyncCallback<SystemSettings>() { + @Override + public void onFailure(Throwable caught) { + groupQueryStatus.setIcons(failIcon); + groupQueryStatus.setDefaultValue("Fail: Unable to retrieve system settings."); + //TODO: update this message + CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); + } + + @Override + public void onSuccess(SystemSettings settings) { + //retrieve relevant information once and update ui + String ldapGroupFilter = settings.get(SystemSetting.LDAP_GROUP_FILTER); + String ldapGroupMember = settings.get(SystemSetting.LDAP_GROUP_MEMBER); + String ldapGroupPagingEnabled = settings.get(SystemSetting.LDAP_GROUP_PAGING); + String ldapGroupPagingValue = settings.get(SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE); + String ldapGroupIsPosix = settings.get(SystemSetting.LDAP_GROUP_USE_POSIX); + groupSearch.setValue(ldapGroupFilter); + groupMember.setValue(ldapGroupMember); + groupQueryPagingItem.setValue(Boolean.valueOf(ldapGroupPagingEnabled)); + groupQueryPagingCountItem.setValue(ldapGroupPagingValue); + groupUsePosixGroupsItem.setValue(Boolean.valueOf(ldapGroupIsPosix)); + ldapGroupSettings.markForRedraw(); + } + }); + } + } + }; + ldapPropertiesTimer.scheduleRepeating(2000); // repeat interval in milliseconds, e.g. 30000 = 30seconds + + //launch operations to populate/refresh LDAP Group Query contents. + final Timer availableGroupsTimer = new Timer() { + public void run() { + if (!queryCompleted) { + //make request to RHQ about state of latest LDAP GWT request + GWTServiceLookup.getLdapService().findAvailableGroupsStatus( + new AsyncCallback<Set<Map<String, String>>>() { + @Override + public void onFailure(Throwable caught) { + groupQueryStatus.setIcons(failIcon); + groupQueryStatus + .setDefaultValue("Fail: Unable to retrieve status for latest AvailableGroups() call."); + //TODO: update this message + CoreGUI.getErrorHandler().handleError(MSG.view_adminRoles_failLdap(), caught); + } + + @Override + public void onSuccess(Set<Map<String, String>> results) { + // Log.debug("@@@@@@@ findAvailableGroupsStatus: SUCCESS:" + System.currentTimeMillis() + // + ":count:" + // + results.size()); + long start = -1, end = -1; + int pageCount = 0; + int resultCountValue = 0; + for (Map<String, String> map : results) { + String key = map.keySet().toArray()[0] + ""; + if (key.equals("query.results.parsed")) { + String value = map.get(key); + resultCountItem.setValue(value); + resultCountValue = Integer.valueOf(value); + } else if (key.equals("query.complete")) { + String value = map.get(key); + queryCompleted = Boolean.valueOf(value); + } else if (key.equals("query.start.time")) { + String value = map.get(key); + start = Long.valueOf(value); + } else if (key.equals("query.end.time")) { + String value = map.get(key); + end = Long.valueOf(value); + } else if (key.equals("query.page.count")) { + String value = map.get(key); + pageCountItem.setValue(value); + pageCount = Integer.valueOf(value); + } + } + //act on status details to add extra perf suggestions + if (queryCompleted) { + groupQueryStatus.setIcons(successIcon); + String success = "Success"; + String tooManyResults = success + ": Too many results."; + String queryTookLongResults = success + ": Query took long to complete."; + String queryTookManyPagesResults = success + ": Query required a lot of paging."; + //TODO: add in extra information about results. + if (resultCountValue > 20000) {//results throttled + groupQueryStatus.setDefaultValue(tooManyResults); + } else if ((end - start) >= 10 * 1000) {// took longer than 10s + groupQueryStatus.setDefaultValue(queryTookLongResults); + } else if (pageCount >= 20) {// took longer than 10s + groupQueryStatus.setDefaultValue(queryTookManyPagesResults); + } + } + availableGroupDetails.markForRedraw(); + //now cancel the timer + cancel(); + } + }); + } + } + }; + availableGroupsTimer.scheduleRepeating(3000); // repeat interval in milliseconds, e.g. 30000 = 30seconds
return availableFilterForm; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/LdapGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/LdapGWTService.java index 8356773..521556b 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/LdapGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/LdapGWTService.java @@ -42,6 +42,11 @@ public interface LdapGWTService extends RemoteService { Set<Map<String, String>> findAvailableGroups() throws RuntimeException;
/** + * @return Map with status of last LDAP groups query available + */ + Set<Map<String, String>> findAvailableGroupsStatus() throws RuntimeException; + + /** * @return Map with LDAP details for user passed. */ Map<String, String> getLdapDetailsFor(String user) throws RuntimeException; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/LdapGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/LdapGWTServiceImpl.java index 3255b8f..28d9323 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/LdapGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/LdapGWTServiceImpl.java @@ -77,6 +77,28 @@ public class LdapGWTServiceImpl extends AbstractGWTServiceImpl implements LdapGW } }
+ @Override + public Set<Map<String, String>> findAvailableGroupsStatus() throws RuntimeException { + try { + //add permissions check + Set<Permission> globalPermissions = authorizationManager.getExplicitGlobalPermissions(getSessionSubject()); + Boolean accessGranted = globalPermissions.contains(Permission.MANAGE_SECURITY); + + Set<Map<String, String>> results = null; + if (accessGranted) { + results = ldapManager.findAvailableGroupsStatus(); + } else { + String message = "User '" + getSessionSubject().getName() + + "' does not have sufficient permissions to query the status of available LDAP groups request."; + log.debug(message); + throw new PermissionException(message); + } + return SerialUtility.prepare(results, "findAvailableGroups"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + public void setLdapGroupsForRole(int roleId, List<String> groupIds) throws RuntimeException { try { //add permissions check diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java index 8a0e321..67abb77 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java @@ -93,9 +93,24 @@ public class LdapGroupManagerBean implements LdapGroupManagerLocal { @EJB private SystemManagerLocal systemManager;
+ private static boolean groupQueryComplete = false; + private static int groupQueryResultCount = 0; + private static long groupQueryStartTime = -1; + private static long groupQueryEndTime = -1; + private static int groupQueryPageCount = 0; + + private void resetGroupQueryDetails() { + groupQueryComplete = false; + groupQueryResultCount = 0; + groupQueryStartTime = -1; + groupQueryEndTime = -1; + groupQueryPageCount = 0; + } public Set<Map<String, String>> findAvailableGroups() { //load current system properties Properties systemConfig = populateProperties(systemManager.getSystemSettings(subjectManager.getOverlord())); + //reset group query details + resetGroupQueryDetails();
//retrieve the filters. String groupFilter = (String) systemConfig.get(SystemSetting.LDAP_GROUP_FILTER.name()); @@ -114,6 +129,29 @@ public class LdapGroupManagerBean implements LdapGroupManagerLocal { return emptyAvailableGroups; }
+ public Set<Map<String, String>> findAvailableGroupsStatus() { + Set<Map<String, String>> availableGroupsQueryStatus = new HashSet<Map<String, String>>(); + + //query.complete => true|false + availableGroupsQueryStatus.add(buildStatusEntry("query.complete", String.valueOf(groupQueryComplete))); + //query.results.parsed => 0...N + availableGroupsQueryStatus.add(buildStatusEntry("query.results.parsed", String.valueOf(groupQueryResultCount))); + //query.start.time => timestamp + availableGroupsQueryStatus.add(buildStatusEntry("query.start.time", String.valueOf(groupQueryStartTime))); + //query.end.time => timestamp|-1 + availableGroupsQueryStatus.add(buildStatusEntry("query.end.time", String.valueOf(groupQueryEndTime))); + //query.page.count => 0...N + availableGroupsQueryStatus.add(buildStatusEntry("query.page.count", String.valueOf(groupQueryPageCount))); + + return availableGroupsQueryStatus; + } + + private Map<String, String> buildStatusEntry(String key, String value) { + HashMap<String, String> status = new HashMap<String, String>(); + status.put(key, value); + return status; + } + public Set<String> findAvailableGroupsFor(String userName) { Properties options = populateProperties(systemManager.getSystemSettings(subjectManager.getOverlord())); String groupFilter = options.getProperty(SystemSetting.LDAP_GROUP_FILTER.name(), ""); @@ -449,8 +487,14 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" String[] baseDNs = baseDN.split(BASEDN_DELIMITER);
for (int x = 0; x < baseDNs.length; x++) { + //update query start time + groupQueryStartTime = System.currentTimeMillis(); + executeGroupSearch(filter, groupDetailsMap, ctx, searchControls, baseDNs, x);
+ //update queryResultCount + groupQueryResultCount = groupDetailsMap.size(); + // continually parsing pages of results until we're done. // only if they're enabled in the UI. if (useQueryPaging) { @@ -472,6 +516,11 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" ctx.setRequestControls(new Control[] { new PagedResultsControl(defaultPageSize, cookie, Control.CRITICAL) }); executeGroupSearch(filter, groupDetailsMap, ctx, searchControls, baseDNs, x); + + //update Query state after each page + groupQueryResultCount = groupDetailsMap.size(); + groupQueryPageCount++; + //empty out cookie cookie = null; //test for further iterations @@ -484,25 +533,6 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" } } } - //continually parsing pages of results until we're done. - while (cookie != null) { - //ensure the next requests contains the session/cookie details - ctx.setRequestControls(new Control[] { new PagedResultsControl(defaultPageSize, cookie, - Control.CRITICAL) }); - executeGroupSearch(filter, groupDetailsMap, ctx, searchControls, baseDNs, x); - //empty out cookie - cookie = null; - //test for further iterations - controls = ctx.getResponseControls(); - if (controls != null) { - for (Control control : controls) { - if (control instanceof PagedResultsResponseControl) { - PagedResultsResponseControl pagedResult = (PagedResultsResponseControl) control; - cookie = pagedResult.getCookie(); - } - } - } - } } } } @@ -522,6 +552,9 @@ SystemSetting.LDAP_GROUP_QUERY_PAGE_SIZE.name(), "" log.error("Unexpected LDAP communciation error:" + iex.getMessage(), iex); throw new LdapCommunicationException(iex); } + //update end of query information + groupQueryEndTime = System.currentTimeMillis(); + groupQueryComplete = true; return groupDetailsMap; }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java index 14945ce..fe3c392 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java @@ -51,6 +51,8 @@ public interface LdapGroupManagerLocal {
Set<Map<String, String>> findAvailableGroups();
+ Set<Map<String, String>> findAvailableGroupsStatus(); + Set<String> findAvailableGroupsFor(String userName);
Map<String, String> findLdapUserDetails(String userName);
commit bc1631522d1dfe1aa3527086ce11b4385160a518 Author: Stefan Negrea snegrea@redhat.com Date: Tue Aug 13 15:21:28 2013 -0500
Update the schema manager to check for schema version at startup. The server should not start if there is schema disagreement.
Also throw an exception during update if the installed schema is too advanced for existing installation.
diff --git a/.classpath b/.classpath index 281a7b3..a61ef29 100644 --- a/.classpath +++ b/.classpath @@ -390,5 +390,6 @@ <classpathentry exported="true" kind="var" path="JDK_HOME/jre/lib/rt.jar"/> <classpathentry kind="var" path="M2_REPO/commons-configuration/commons-configuration/1.6/commons-configuration-1.6.jar"/> <classpathentry kind="var" path="M2_REPO/org/apache/maven/plugin-tools/maven-plugin-annotations/3.2/maven-plugin-annotations-3.2.jar"/> + <classpathentry kind="var" path="M2_REPO/org/jboss/jboss-vfs/3.1.0.Final/jboss-vfs-3.1.0.Final.jar"/> <classpathentry kind="output" path="eclipse-classes"/> </classpath> diff --git a/modules/common/cassandra-schema/pom.xml b/modules/common/cassandra-schema/pom.xml index 8e3b44a..6fb2915 100644 --- a/modules/common/cassandra-schema/pom.xml +++ b/modules/common/cassandra-schema/pom.xml @@ -47,6 +47,13 @@ <artifactId>cassandra-driver-core</artifactId> <version>${cassandra.driver.version}</version> </dependency> + + <dependency> + <groupId>org.jboss</groupId> + <artifactId>jboss-vfs</artifactId> + <version>${jboss-vfs.version}</version> + </dependency> + </dependencies>
<build> diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java index baf7c23..7b8c520 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/AbstractManager.java @@ -92,7 +92,7 @@ abstract class AbstractManager { }
/** - * Init the Cassandra cluster session with the username and password provided + * Init the storage cluster session with the username and password provided * at creation. */ protected void initClusterSession() { @@ -100,7 +100,7 @@ abstract class AbstractManager { }
/** - * Init the Cassandra cluster session with provided username and password. + * Init the storage cluster session with provided username and password. * * @param username * @param password @@ -125,7 +125,7 @@ abstract class AbstractManager { }
/** - * Shutdown the Cassandra cluster connection. + * Shutdown the storage cluster connection. */ protected void shutdownClusterConnection() { log.info("Shutting down existing cluster connections"); @@ -135,7 +135,7 @@ abstract class AbstractManager { }
/** - * Get cluster size. + * Get storage cluster size. * * @return cluster size */ @@ -158,7 +158,7 @@ abstract class AbstractManager { }
/** - * Runs a CQL query to check the existence of the RHQ user + * Runs a CQL query to check the existence of the RHQ user on the storage cluster. * * @return true if the RHQ user exists, false otherwise */ @@ -173,7 +173,7 @@ abstract class AbstractManager { }
/** - * Run a CQL query to check the existence of the RHQ schema + * Run a CQL query to check the existence of the RHQ schema. * * @return true if the RHQ schema exists, false otherwise */ @@ -192,11 +192,11 @@ abstract class AbstractManager { }
/** - * Run a CQL query to retrieve the current RHQ schema version + * Run a CQL query to retrieve the installed storage schema version. * * @return current RHQ schema version */ - protected int getSchemaVersion() { + protected int getInstalledSchemaVersion() { int maxVersion = 0; try { ResultSet resultSet = executeManagementQuery(Query.VERSION); diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java index 8d28bfa..1a82779 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/SchemaManager.java @@ -80,7 +80,7 @@ public class SchemaManager { }
/** - * Install and update the RHQ schema. + * Install and update the storage cluster schema. * * @throws Exception */ @@ -90,7 +90,18 @@ public class SchemaManager { }
/** - * Drop RHQ schema and revert the database to pre-RHQ state. + * Check the existing storage cluster schema version to ensure it is compatible with the + * current installation. + * + * @throws Exception + */ + public void checkCompatibility() throws Exception { + VersionManager version = new VersionManager(username, password, nodes); + version.checkCompatibility(); + } + + /** + * Drop storage cluster schema and revert the storage cluster to pre-RHQ state. * * @throws Exception */ diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/UpdateFolder.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/UpdateFolder.java index 84cb515..31266ca 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/UpdateFolder.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/UpdateFolder.java @@ -30,6 +30,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.JarURLConnection; import java.net.URL; +import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -41,6 +42,8 @@ import java.util.jar.JarFile; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.jboss.vfs.VirtualFile; + /** * @author Stefan Negrea */ @@ -83,6 +86,19 @@ class UpdateFolder { }
/** + * The version represented by the latest/highest xml update file. + * + * @return the version + */ + public int getLatestVersion() { + if (this.updateFiles != null && this.updateFiles.size() > 0) { + return this.updateFiles.get(this.updateFiles.size() - 1).extractVersion(); + } + + return 0; + } + + /** * Loads the initial set of update files based on the input folder. * * @return list of update files @@ -115,9 +131,13 @@ class UpdateFolder { } } } else if (resourceFolderURL.getProtocol().equals("vfs")) { - // TODO need to add support for VFS if going to use inside EAP - throw new RuntimeException("The URL protocol [" + resourceFolderURL.getProtocol() + "] is not " + - "supported"); + URLConnection conn = resourceFolderURL.openConnection(); + VirtualFile virtualFolder = (VirtualFile)conn.getContent(); + for (VirtualFile virtualChild : virtualFolder.getChildren()) { + if (!virtualChild.isDirectory()) { + files.add(new UpdateFile(virtualChild.getPathNameRelativeTo(virtualFolder.getParent()))); + } + } } else { // In the event we get another protocol that we do not recognize, throw an // exception instead of failing silently. diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java index 794e991..ec54a0c 100644 --- a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/VersionManager.java @@ -34,6 +34,8 @@ import com.datastax.driver.core.exceptions.AuthenticationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.rhq.cassandra.schema.exception.InstalledSchemaTooAdvancedException; +import org.rhq.cassandra.schema.exception.InstalledSchemaTooOldException; import org.rhq.core.domain.cloud.StorageNode;
/** @@ -73,14 +75,14 @@ class VersionManager extends AbstractManager { * @throws Exception */ public void install() throws Exception { - log.info("Preparing to install schema"); + log.info("Preparing to install storage schema");
boolean clusterSessionInitialized = false; try { initClusterSession(); clusterSessionInitialized = true; } catch (AuthenticationException e) { - log.debug("Authentication exception. Will now attempt to create the schema."); + log.debug("Authentication exception. Will now attempt to create the storage schema."); log.debug(e); } finally { shutdownClusterConnection(); @@ -119,7 +121,7 @@ class VersionManager extends AbstractManager { if (!schemaExists()) { execute(updateFolder.getUpdateFiles().get(0), properties); } else { - log.info("RHQ schema already exists."); + log.info("Storage schema already exists."); } } catch (Exception ex) { log.error(ex); @@ -147,28 +149,44 @@ class VersionManager extends AbstractManager { initClusterSession();
if (!schemaExists()) { - log.error("Schema not installed."); - throw new RuntimeException("Schema not installed propertly, cannot apply schema updates."); + log.error("Storage schema not installed."); + throw new RuntimeException("Storage schema not installed propertly, cannot apply schema updates."); }
UpdateFolder updateFolder = new UpdateFolder(Task.Update.getFolder());
- int currentSchemaVersion = getSchemaVersion(); - log.info("Current schema version is " + currentSchemaVersion); - updateFolder.removeAppliedUpdates(currentSchemaVersion); + int installedSchemaVersion = getInstalledSchemaVersion(); + log.info("Installed storage schema version is " + installedSchemaVersion);
- if (updateFolder.getUpdateFiles().size() == 0) { - log.info("RHQ schema is current! No updates applied."); + int requiredSchemaVersion = updateFolder.getLatestVersion(); + log.info("Required storage schema version is " + requiredSchemaVersion); + + if (requiredSchemaVersion == installedSchemaVersion) { + log.info("Storage schema version is current ( " + installedSchemaVersion + " ). No updates applied."); + } else if (requiredSchemaVersion < installedSchemaVersion) { + log.error("Installed storage cluster schema version: " + installedSchemaVersion + + ". Required schema version: " + requiredSchemaVersion + + ". Storage cluster schema has been updated beyond the capability of the existing server installation."); + throw new InstalledSchemaTooAdvancedException(); } else { - for (UpdateFile updateFile : updateFolder.getUpdateFiles()) { - execute(updateFile); + log.info("Storage schema requires udpates. Updating from version " + installedSchemaVersion + + " to version " + requiredSchemaVersion + "."); + + updateFolder.removeAppliedUpdates(installedSchemaVersion); + + if (updateFolder.getUpdateFiles().size() == 0) { + log.info("Storage schema is current! No updates applied."); + } else { + for (UpdateFile updateFile : updateFolder.getUpdateFiles()) { + execute(updateFile);
- Properties versionProperties = new Properties(); - versionProperties.put("version", updateFile.extractVersion() + ""); - versionProperties.put("time", System.currentTimeMillis() + ""); - executeManagementQuery(Query.INSERT_SCHEMA_VERSION, versionProperties); + Properties versionProperties = new Properties(); + versionProperties.put("version", updateFile.extractVersion() + ""); + versionProperties.put("time", System.currentTimeMillis() + ""); + executeManagementQuery(Query.INSERT_SCHEMA_VERSION, versionProperties);
- log.info("RHQ schema update " + updateFile +" applied."); + log.info("Storage schema update " + updateFile + " applied."); + } } } } finally { @@ -185,7 +203,7 @@ class VersionManager extends AbstractManager { * @throws Exception */ public void drop() throws Exception { - log.info("Preparing to drop RHQ schema"); + log.info("Preparing to drop storage schema.");
UpdateFolder updateFolder = new UpdateFolder(Task.Drop.getFolder()); Properties properties = new Properties(System.getProperties()); @@ -209,22 +227,60 @@ class VersionManager extends AbstractManager { if (schemaExists()) { //2. Drop RHQ schema execute(updateFolder.getUpdateFiles().get(1), properties); - log.info("RHQ schema dropped."); + log.info("Storage schema dropped."); } else { - log.info("RHQ schema does not exist. Drop operation not required."); + log.info("Storage schema does not exist. Drop operation not required."); }
if (userExists()) { //3. Drop RHQ user execute(updateFolder.getUpdateFiles().get(2), properties); - log.info("RHQ admin user dropped."); + log.info("RHQ admin user dropped from storage cluster."); } else { - log.info("RHQ admin user does not exist. Drop operation not required."); + log.info("RHQ admin user does not exist on the storage cluster. Drop operation not required."); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + shutdownClusterConnection(); + } + } + + /** + * Check storage cluster schema version compatibility. + * If the version installed on the storage cluster is too advanced or too old compared + * to the version available in the current schema manager an error will thrown. + * + * @throws Exception schema compatibility exception + */ + public void checkCompatibility() throws Exception { + log.info("Preparing to check storage schema compatibility."); + try { + initClusterSession(); + + int installedSchemaVersion = this.getInstalledSchemaVersion(); + + UpdateFolder folder = new UpdateFolder(Task.Update.getFolder()); + int requiredSchemaVersion = folder.getLatestVersion(); + + if (installedSchemaVersion < requiredSchemaVersion) { + log.error("Storage cluster schema version:" + installedSchemaVersion + ". Required schema version: " + + requiredSchemaVersion + ". Please update storage cluster schema version."); + throw new InstalledSchemaTooOldException(); + } + + if (installedSchemaVersion > requiredSchemaVersion) { + log.error("Storage cluster schema version:" + installedSchemaVersion + ". Required schema version: " + + requiredSchemaVersion + + ". Storage clutser has been updated beyond the capability of the current server installation."); + throw new InstalledSchemaTooAdvancedException(); } } catch (Exception e) { throw new RuntimeException(e); } finally { shutdownClusterConnection(); + + log.info("Completed check for storage schema compatibility."); } } } diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java new file mode 100644 index 0000000..2f83ef5 --- /dev/null +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooAdvancedException.java @@ -0,0 +1,38 @@ +/* + * + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, 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.cassandra.schema.exception; + + +/** + * @author Stefan Negrea + */ +public class InstalledSchemaTooAdvancedException extends Exception { + + public InstalledSchemaTooAdvancedException() { + super( + "Storage schema is too advanced for the current installation. Schema revisions have been applied beyond the capability of the installation."); + } +} \ No newline at end of file diff --git a/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java new file mode 100644 index 0000000..4da863b --- /dev/null +++ b/modules/common/cassandra-schema/src/main/java/org/rhq/cassandra/schema/exception/InstalledSchemaTooOldException.java @@ -0,0 +1,38 @@ +/* + * + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, 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.cassandra.schema.exception; + + +/** + * @author Stefan Negrea + */ +public class InstalledSchemaTooOldException extends Exception { + + public InstalledSchemaTooOldException() { + super( + "Storage schema needs to be updated. The schema manager contains updates not yet applied to the storage cluster installation."); + } +} \ No newline at end of file diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/listener/CoreGuiServletContextListener.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/listener/CoreGuiServletContextListener.java index 8260327..67e4389 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/listener/CoreGuiServletContextListener.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/listener/CoreGuiServletContextListener.java @@ -54,7 +54,11 @@ public class CoreGuiServletContextListener implements ServletContextListener { scheduledExecutorService.schedule(new Runnable() { @Override public void run() { - startupBean.init(); + try { + startupBean.init(); + } catch (Exception e) { + shutdownListener.handleNotification(); + } } }, 10, SECONDS); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java index 6828b12..dbd599a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/storage/StorageClientManagerBean.java @@ -40,6 +40,7 @@ import com.datastax.driver.core.Session; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.rhq.cassandra.schema.SchemaManager; import org.rhq.cassandra.util.ClusterBuilder; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.util.StringUtil; @@ -86,7 +87,6 @@ public class StorageClientManagerBean { String username = getRequiredStorageProperty(USERNAME_PROP); String password = getRequiredStorageProperty(PASSWORD_PROP);
- metricsConfiguration = new MetricsConfiguration(); List<StorageNode> storageNodes = storageNodeManager.getStorageNodes(); if (storageNodes.isEmpty()) { throw new IllegalStateException( @@ -94,12 +94,17 @@ public class StorageClientManagerBean { + "result of running dbsetup or deleting rows from rhq_storage_node table. Please re-install the " + "storage node to fix this issue."); } + + checkSchemaCompability(username, password, storageNodes); + + Session wrappedSession = createSession(username, password, storageNodeManager.getStorageNodes()); session = new StorageSession(wrappedSession);
storageClusterMonitor = new StorageClusterMonitor(); session.addStorageStateListener(storageClusterMonitor);
+ metricsConfiguration = new MetricsConfiguration(); metricsDAO = new MetricsDAO(session, metricsConfiguration);
initMetricsServer(); @@ -108,6 +113,22 @@ public class StorageClientManagerBean { log.info("Storage client subsystem is now initialized"); }
+ /** + * Checks storage node schema compatibility. + * + * @param username username + * @param password password + * @param storageNodes storage nodes + */ + private void checkSchemaCompability(String username, String password, List<StorageNode> storageNodes) { + SchemaManager schemaManager = new SchemaManager(username, password, storageNodes); + try { + schemaManager.checkCompatibility(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + public synchronized void shutdown() { if (!initialized) { log.info("Storage client subsystem is already shut down. Skipping shutdown steps."); diff --git a/pom.xml b/pom.xml index 3f2adbd..eb71cb3 100644 --- a/pom.xml +++ b/pom.xml @@ -108,6 +108,8 @@ <jboss-modules.version>1.1.1.GA</jboss-modules.version> <jboss-dmr.version>1.1.1.Final</jboss-dmr.version> <jboss-msc.version>1.0.2.GA</jboss-msc.version> + <jboss-vfs.version>3.1.0.Final</jboss-vfs.version> +
<!-- Not Provided - some of these are needed by the agent --> <jboss-annotations.version>4.2.3.GA</jboss-annotations.version>
commit a30f502b1d3d7dada5c21dc8912bb92237d051d1 Author: Jirka Kremser jkremser@redhat.com Date: Tue Aug 13 20:43:51 2013 +0200
Improvements to cluster-wide alert UI: improved grouping, headers of groups, link to definition.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java index 9c26b5c..0821585 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import com.smartgwt.client.data.Record; import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.types.ImageStyle; -import com.smartgwt.client.types.SummaryFunctionType; import com.smartgwt.client.widgets.Img; import com.smartgwt.client.widgets.grid.CellFormatter; import com.smartgwt.client.widgets.grid.ListGrid; @@ -37,6 +36,8 @@ import org.rhq.enterprise.gui.coregui.client.ImageManager; import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.alert.AlertDataSource; import org.rhq.enterprise.gui.coregui.client.alert.AlertHistoryView; +import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction; +import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement; import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil; import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
@@ -45,6 +46,7 @@ import org.rhq.enterprise.gui.coregui.client.util.StringUtility; * */ public class StorageNodeAlertHistoryView extends AlertHistoryView { + private boolean isGouped = true;
public StorageNodeAlertHistoryView(String tableTitle, int[] resourceIds) { super(tableTitle, resourceIds); @@ -64,8 +66,32 @@ public class StorageNodeAlertHistoryView extends AlertHistoryView { continue; } if (AlertCriteria.SORT_FIELD_CTIME.equals(field.getName())) { field.setWidth(240); + field.setShowGridSummary(true); + field.setShowGroupSummary(true); + field.setSummaryFunction(new SummaryFunction() { + public Object getSummaryValue(Record[] records, ListGridField field) { + if (records != null && records.length > 0 && records[0] != null) { + Integer resourceId = records[0].getAttributeAsInt(AncestryUtil.RESOURCE_ID); + Integer defId = records[0].getAttributeAsInt("definitionId"); + String url = LinkManager.getSubsystemAlertDefinitionLink(resourceId, defId); + return LinkManager.getHref(url, "Link to Definition"); + } else return ""; + } + }); + field.setCellFormatter(new CellFormatter() { + public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { + if (listGridRecord.getAttribute("groupValue") != null) { + return (String) o; + } + Integer resourceId = listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID); + Integer defId = listGridRecord.getAttributeAsInt("definitionId"); + String url = LinkManager.getSubsystemAlertDefinitionLink(resourceId, defId); + return LinkManager.getHref(url, o.toString()); + } + }); + field.setWidth(240); } else if ("conditionValue".equals(field.getName())) { - field.setWidth(90); + field.setWidth(140); } else if ("acknowledgingSubject".equals(field.getName())) { field.setSummaryFunction(new SummaryFunction() { public Object getSummaryValue(Record[] records, ListGridField field) { @@ -74,8 +100,8 @@ public class StorageNodeAlertHistoryView extends AlertHistoryView { if (record.getAttribute("acknowledgingSubject") != null) { count++; } - } - return count + " Unacked"; + } + return "(" + count + " / " + records.length + ")"; } }); field.setCellFormatter(new CellFormatter() { @@ -100,20 +126,12 @@ public class StorageNodeAlertHistoryView extends AlertHistoryView { newFields.add(1, field); continue; } else if ("name".equals(field.getName())) { - field.setShowGridSummary(true); - field.setShowGroupSummary(true); - field.setSummaryFunction(SummaryFunctionType.COUNT); field.setCellFormatter(new CellFormatter() { public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { - if (listGridRecord.getAttribute("groupValue") != null) { - return (String) o; - } - Integer resourceId = listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID); - Integer defId = listGridRecord.getAttributeAsInt("definitionId"); - String url = LinkManager.getSubsystemAlertDefinitionLink(resourceId, defId); - return LinkManager.getHref(url, o.toString()); + return o.toString(); } }); + field.setHidden(true); } newFields.add(field); } @@ -142,6 +160,9 @@ public class StorageNodeAlertHistoryView extends AlertHistoryView { if (value == null) { return ""; } + if (record.getAttribute("groupValue") != null) { + return value.toString(); + } String detailsUrl = getDetailUrlFromRecord(record); String formattedValue = StringUtility.escapeHtml(value.toString()); return LinkManager.getHref(detailsUrl, formattedValue); @@ -169,5 +190,20 @@ public class StorageNodeAlertHistoryView extends AlertHistoryView { throw new IllegalArgumentException(msg); } } - + + @Override + protected void configureTable() { + super.configureTable(); + addTableAction("(Un)Group Alerts", new AbstractTableAction(TableActionEnablement.ALWAYS) { + public void executeAction(ListGridRecord[] selection, Object actionValue) { + if (isGouped) { + getListGrid().ungroup(); + } else { + getListGrid().groupBy("name"); + } + isGouped = !isGouped; + refreshTableInfo(); + } + }); + } }
commit 07947430b1bd4c9179cc0af53a754f6a52dd90c6 Author: Jirka Kremser jkremser@redhat.com Date: Tue Aug 13 18:43:59 2013 +0200
Storage node configuration: added check for Max Heap Size (-Xmx) > Heap New Size (-Xmn).
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java index f1c0003..7bcf2cd 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java @@ -19,8 +19,10 @@ package org.rhq.enterprise.gui.coregui.client.admin.storage;
import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback; @@ -194,7 +196,7 @@ public class StorageNodeConfigurationEditor extends EnhancedVLayout implements R FIELD_HEAP_MAX, "Max Heap Size", configuration.getHeapSize(), - "The maximum heap size. This value will be used with the -Xmx JVM option. The value should be an integer with a suffix of M or G to indicate megabytes or gigabytes.")); + "The maximum heap size. This value will be used with the -Xmx JVM option. If you are going to increase/decrease this value, then you should also increase/decrease the new generation proportionally. The value should be an integer with a suffix of M or G to indicate megabytes or gigabytes.")); items .addAll(buildOneFormRowWithCombobox( FIELD_HEAP_NEW, @@ -233,6 +235,13 @@ public class StorageNodeConfigurationEditor extends EnhancedVLayout implements R saveButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent clickEvent) { if (form.validate()) { + if (!checkNewHeapLowerThanMaxHeap()) { + Map<String, String> errors = new HashMap<String, String>(2); + errors.put(FIELD_HEAP_MAX, "Should be lower than Heap New Size."); + errors.put(FIELD_HEAP_NEW, "Should be higher than Max Heap Size."); + form.setErrors(errors, true); + return; + } SC.ask( "Changing the storage node configuration requires restart of storage node. Do you want to continue?", new BooleanCallback() { @@ -263,6 +272,30 @@ public class StorageNodeConfigurationEditor extends EnhancedVLayout implements R return configuration; }
+ private boolean checkNewHeapLowerThanMaxHeap() { + // let's be paranoid + Object maxHeapObject = form.getField(FIELD_HEAP_MAX).getValue(); + Object newHeapObject = form.getField(FIELD_HEAP_NEW).getValue(); + + String maxHeapString = maxHeapObject != null ? maxHeapObject.toString().trim() : ""; + String newHeapString = newHeapObject != null ? newHeapObject.toString().trim() : ""; + + if (maxHeapString.isEmpty() || newHeapString.isEmpty()) { + return false; + } + + int maxHeap = Integer.parseInt(maxHeapString.substring(0, maxHeapString.length() - 2)); + int newHeap = Integer.parseInt(newHeapString.substring(0, newHeapString.length() - 2)); + + boolean isMaxHeapInMegs = maxHeapString.toLowerCase().indexOf("m") != -1; + boolean isNewHeapInMegs = newHeapString.toLowerCase().indexOf("m") != -1; + + maxHeap = isMaxHeapInMegs ? maxHeap : maxHeap * 1024; + newHeap = isNewHeapInMegs ? newHeap : newHeap * 1024; + + return newHeap < maxHeap; + } + private String getJVMMemoryString(String raw) { if (raw == null || raw.trim().isEmpty()) { throw new IllegalArgumentException("input string is null or empty");
commit 9a9bd9cd55ff4c5094271f8c33bbe885da3d3fb7 Author: Jirka Kremser jkremser@redhat.com Date: Tue Aug 13 12:57:44 2013 +0200
api checks: adding the return type of intentionally changed method for clirr to make it work
diff --git a/modules/core/domain/intentional-api-changes-since-4.8.0.xml b/modules/core/domain/intentional-api-changes-since-4.8.0.xml index b14d38e..6a22ea5 100644 --- a/modules/core/domain/intentional-api-changes-since-4.8.0.xml +++ b/modules/core/domain/intentional-api-changes-since-4.8.0.xml @@ -11,7 +11,7 @@ <difference> <className>org/rhq/core/domain/cloud/Server</className> <differenceType>7004</differenceType><!-- num argments changed --> - <method>clearStatus()</method> + <method>void clearStatus()</method> <justification> This class is not exposed remotely. The previous method signature was doing a blind clear of the status. The new method will clear only the specified status.
commit 10cd06241505b5350486b34f9b866c59abf3b3cf Author: Jirka Kremser jkremser@redhat.com Date: Mon Aug 12 21:40:05 2013 +0200
New component for storage node alerts (derived from AlertHistoryView); Predefined alert templates shoud have the description fields correctly filled.; calling the update configuration method in an async way.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java index 5538db5..cd0ec54 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAdminView.java @@ -18,14 +18,22 @@ */ package org.rhq.enterprise.gui.coregui.client.admin.storage;
+import java.util.ArrayList; import java.util.EnumSet;
import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.data.DataSourceField; +import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.widgets.Label; +import com.smartgwt.client.widgets.grid.CellFormatter; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; import com.smartgwt.client.widgets.tab.events.TabSelectedEvent; import com.smartgwt.client.widgets.tab.events.TabSelectedHandler;
+import org.rhq.core.domain.criteria.AlertCriteria; import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; @@ -34,17 +42,22 @@ import org.rhq.core.domain.util.collection.ArrayUtils; import org.rhq.enterprise.gui.coregui.client.BookmarkableView; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.IconEnum; +import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.ViewPath; import org.rhq.enterprise.gui.coregui.client.admin.AdministrationView; +import org.rhq.enterprise.gui.coregui.client.alert.AlertDataSource; import org.rhq.enterprise.gui.coregui.client.alert.AlertHistoryView; import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTab; import org.rhq.enterprise.gui.coregui.client.components.tab.NamedTabSet; +import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.components.view.HasViewName; 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.groups.detail.configuration.GroupResourceConfigurationEditView; +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.util.Log; +import org.rhq.enterprise.gui.coregui.client.util.StringUtility; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.enterprise.gui.coregui.client.util.message.Message;
@@ -120,7 +133,8 @@ public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewNa tabset.getTabByName(tabInfo.name.getName()).setPane(new Label("in progress..")); } else if (tabInfo.equals(alertsTabInfo)) { if (resIds != null) { - tabset.getTabByName(tabInfo.name.getName()).setPane(new AlertHistoryView("storageNodesAlerts", resIds)); + tabset.getTabByName(tabInfo.name.getName()).setPane( + new StorageNodeAlertHistoryView("storageNodesAlerts", resIds)); } else { GWTServiceLookup.getStorageService().findResourcesWithAlertDefinitions(new AsyncCallback<Integer[]>() { @Override @@ -137,7 +151,7 @@ public class StorageNodeAdminView extends EnhancedVLayout implements/* HasViewNa } else { resIds = ArrayUtils.unwrapArray(result); tabset.getTabByName(tabInfo.name.getName()).setPane( - new AlertHistoryView("storageNodesAlerts", resIds)); + new StorageNodeAlertHistoryView("storageNodesAlerts", resIds)); tabset.selectTab(tabInfo.index); } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java new file mode 100644 index 0000000..9c26b5c --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeAlertHistoryView.java @@ -0,0 +1,173 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.admin.storage; + +import java.util.ArrayList; + +import com.smartgwt.client.data.Record; +import com.smartgwt.client.types.GroupStartOpen; +import com.smartgwt.client.types.ImageStyle; +import com.smartgwt.client.types.SummaryFunctionType; +import com.smartgwt.client.widgets.Img; +import com.smartgwt.client.widgets.grid.CellFormatter; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.grid.SummaryFunction; + +import org.rhq.core.domain.criteria.AlertCriteria; +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.alert.AlertDataSource; +import org.rhq.enterprise.gui.coregui.client.alert.AlertHistoryView; +import org.rhq.enterprise.gui.coregui.client.inventory.resource.AncestryUtil; +import org.rhq.enterprise.gui.coregui.client.util.StringUtility; + +/** + * @author Jirka Kremser + * + */ +public class StorageNodeAlertHistoryView extends AlertHistoryView { + + public StorageNodeAlertHistoryView(String tableTitle, int[] resourceIds) { + super(tableTitle, resourceIds); + } + + @Override + public AlertDataSource getDataSource() { + return new AlertDataSource() { + @Override + public ArrayList<ListGridField> getListGridFields() { + ArrayList<ListGridField> fields = super.getListGridFields(); + ArrayList<ListGridField> newFields = new ArrayList<ListGridField>(fields.size()); + for (ListGridField field : fields) { + if ("priority".equals(field.getName()) + || AncestryUtil.RESOURCE_NAME.equals(field.getName()) + || AncestryUtil.RESOURCE_ANCESTRY.equals(field.getName())) { + continue; + } if (AlertCriteria.SORT_FIELD_CTIME.equals(field.getName())) { + field.setWidth(240); + } else if ("conditionValue".equals(field.getName())) { + field.setWidth(90); + } else if ("acknowledgingSubject".equals(field.getName())) { + field.setSummaryFunction(new SummaryFunction() { + public Object getSummaryValue(Record[] records, ListGridField field) { + int count = 0; + for (Record record : records) { + if (record.getAttribute("acknowledgingSubject") != null) { + count++; + } + } + return count + " Unacked"; + } + }); + field.setCellFormatter(new CellFormatter() { + public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { + if (listGridRecord.getAttribute("groupValue") != null) { + return (String) o; + } + String ackSubject = listGridRecord.getAttribute("acknowledgingSubject"); + if (ackSubject == null) { + return " "; + } else { + Img checkedImg = new Img(ImageManager.getAlertStatusCheckedIcon(), 80, 16); + checkedImg.setImageType(ImageStyle.CENTER); + return checkedImg.getInnerHTML(); + } + } + }); + + field.setShowGridSummary(false); + field.setShowGroupSummary(true); + field.setWidth(90); + newFields.add(1, field); + continue; + } else if ("name".equals(field.getName())) { + field.setShowGridSummary(true); + field.setShowGroupSummary(true); + field.setSummaryFunction(SummaryFunctionType.COUNT); + field.setCellFormatter(new CellFormatter() { + public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { + if (listGridRecord.getAttribute("groupValue") != null) { + return (String) o; + } + Integer resourceId = listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID); + Integer defId = listGridRecord.getAttributeAsInt("definitionId"); + String url = LinkManager.getSubsystemAlertDefinitionLink(resourceId, defId); + return LinkManager.getHref(url, o.toString()); + } + }); + } + newFields.add(field); + } + ListGridField descriptionField = new ListGridField("description", MSG.common_title_description()); + descriptionField.setCanSortClientOnly(true); + newFields.add(descriptionField); + return newFields; + } + }; + } + + @Override + protected void configureListGrid(ListGrid grid) { + ListGrid listGrid = super.getListGrid(); + listGrid.setGroupStartOpen(GroupStartOpen.ALL); + listGrid.setShowGroupSummary(true); + listGrid.setShowGroupSummaryInHeader(true); + + listGrid.setGroupByField("name"); + } + + @Override + protected CellFormatter getDetailsLinkColumnCellFormatter() { + return new CellFormatter() { + public String format(Object value, ListGridRecord record, int i, int i1) { + if (value == null) { + return ""; + } + String detailsUrl = getDetailUrlFromRecord(record); + String formattedValue = StringUtility.escapeHtml(value.toString()); + return LinkManager.getHref(detailsUrl, formattedValue); + } + }; + } + + @Override + public void showDetails(ListGridRecord record) { + CoreGUI.goToView(getDetailUrlFromRecord(record)); + } + + private String getDetailUrlFromRecord(ListGridRecord record) { + if (record == null) { + throw new IllegalArgumentException("'record' parameter is null."); + } + Integer recordId = getId(record); + Integer resourceId = record.getAttributeAsInt(AncestryUtil.RESOURCE_ID); + if (recordId != null && recordId.intValue() > 0 && resourceId != null && resourceId > 0) { + return "#Resource/" + resourceId + "/Alerts/History/" + convertIDToCurrentViewPath(recordId); + } else { + String msg = MSG.view_tableSection_error_badId(this.getClass().toString(), (recordId == null) ? "null" + : recordId.toString()); + CoreGUI.getErrorHandler().handleError(msg); + throw new IllegalArgumentException(msg); + } + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java index 3c4923b..f1c0003 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/admin/storage/StorageNodeConfigurationEditor.java @@ -74,15 +74,12 @@ public class StorageNodeConfigurationEditor extends EnhancedVLayout implements R
private void save() { updateConfiguration(); - GWTServiceLookup.getStorageService().updateConfiguration(configuration, new AsyncCallback<Boolean>() { - public void onSuccess(Boolean result) { - if (result) { - Message msg = new Message("Storage node settings were successfully updated.", Message.Severity.Info); - CoreGUI.getMessageCenter().notify(msg); - } else { - onFailure(new Exception("Operation failed.")); - } + GWTServiceLookup.getStorageService().updateConfiguration(configuration, new AsyncCallback<Void>() { + public void onSuccess(Void result) { + Message msg = new Message("Storage node settings were successfully updated.", Message.Severity.Info); + CoreGUI.getMessageCenter().notify(msg); } + public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError("Unable to update the storage node settings.", caught); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java index 6e6df57..957bf34 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/StorageGWTService.java @@ -84,5 +84,5 @@ public interface StorageGWTService extends RemoteService {
StorageNodeConfigurationComposite retrieveConfiguration(StorageNode storageNode) throws RuntimeException;
- boolean updateConfiguration(StorageNodeConfigurationComposite storageNodeConfiguration) throws RuntimeException; + void updateConfiguration(StorageNodeConfigurationComposite storageNodeConfiguration) throws RuntimeException; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java index 4a01427..f7f7442 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/StorageGWTServiceImpl.java @@ -163,9 +163,9 @@ public class StorageGWTServiceImpl extends AbstractGWTServiceImpl implements Sto }
@Override - public boolean updateConfiguration(StorageNodeConfigurationComposite storageNodeConfiguration) throws RuntimeException { + public void updateConfiguration(StorageNodeConfigurationComposite storageNodeConfiguration) throws RuntimeException { try { - return storageNodeManager.updateConfiguration(getSessionSubject(), storageNodeConfiguration); + storageNodeManager.updateConfigurationAsync(getSessionSubject(), storageNodeConfiguration); } catch (Throwable t) { throw getExceptionToThrowToClient(t); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 053b57e..9e41692 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -36,6 +36,11 @@ import java.util.Map; import java.util.Queue; import java.util.Set;
+import org.rhq.enterprise.server.storage.StorageClusterSettings; +import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerBean; +import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; + +import javax.ejb.Asynchronous; import javax.ejb.EJB; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; @@ -83,9 +88,6 @@ import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.rest.reporting.MeasurementConverter; import org.rhq.enterprise.server.scheduler.SchedulerLocal; -import org.rhq.enterprise.server.storage.StorageClusterSettings; -import org.rhq.enterprise.server.storage.StorageClusterSettingsManagerBean; -import org.rhq.enterprise.server.storage.StorageNodeOperationsHandlerLocal; import org.rhq.enterprise.server.util.CriteriaQueryGenerator; import org.rhq.enterprise.server.util.CriteriaQueryRunner; import org.rhq.enterprise.server.util.LookupUtil; @@ -624,6 +626,12 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
return configuration; } + + @Override + @Asynchronous + public void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) { + updateConfiguration(subject, storageNodeConfiguration); + }
@Override public boolean updateConfiguration(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration) { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java index 0c1b0ab..b5ee7f0 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java @@ -65,6 +65,8 @@ public interface StorageNodeManagerLocal { StorageNodeConfigurationComposite retrieveConfiguration(Subject subject, StorageNode storageNode);
boolean updateConfiguration(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration); + + void updateConfigurationAsync(Subject subject, StorageNodeConfigurationComposite storageNodeConfiguration);
/** * Fetches the list of StorageNode entities based on provided criteria. diff --git a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java index 840477c..f752d1d 100644 --- a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java +++ b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java @@ -258,6 +258,7 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone newTemplate.setResourceType(resourceType); newTemplate.setPriority(AlertPriority.MEDIUM); newTemplate.setConditionExpression(BooleanExpression.ANY); + newTemplate.setDescription(storageNodeHighHeapTemplate.getDescription()); newTemplate.setRecoveryId(0); newTemplate.setEnabled(true);
@@ -308,6 +309,7 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone newTemplate.setResourceType(resourceType); newTemplate.setPriority(AlertPriority.MEDIUM); newTemplate.setConditionExpression(BooleanExpression.ANY); + newTemplate.setDescription(storageNodeHighDiskUsageTemplate.getDescription()); newTemplate.setRecoveryId(0); newTemplate.setEnabled(true);
@@ -377,6 +379,7 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone newTemplate.setResourceType(resourceType); newTemplate.setPriority(AlertPriority.MEDIUM); newTemplate.setConditionExpression(BooleanExpression.ANY); + newTemplate.setDescription(storageNodeSnapshotFailureTemplate.getDescription()); newTemplate.setRecoveryId(0); newTemplate.setEnabled(true);
commit f7eb3a4d1dff898093cac9cbc84e7495171cbd35 Author: Stefan Negrea snegrea@redhat.com Date: Mon Aug 12 12:17:17 2013 -0500
Slight change to the comment text.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java index 7fa82f7..671db6b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java @@ -88,9 +88,9 @@ import org.rhq.core.domain.resource.Agent; + " AND ( s.name <> :thisServerName OR :thisServerName IS NULL ) "), // @NamedQuery(name = Server.QUERY_UPDATE_STATUS_BY_NAME, query = "" // + " UPDATE Server s " // - + " SET s.status = 3 " //change this to the only value possible before adding MANUAL_MAINTENANCE_MODE - //this status should never be set to negative numbers since they are values allowed - //by the bitmask. + + " SET s.status = 3 " //Change this to the only value possible before adding MANUAL_MAINTENANCE_MODE. + //This status should never be set to negative since negative values are not + //allowed by the bitmask. + " WHERE s.status = 0 ") }) @SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_SERVER_ID_SEQ", sequenceName = "RHQ_SERVER_ID_SEQ") @Table(name = "RHQ_SERVER")
commit b7e1df4a48e60dc31aff52756368f5713be48cf5 Author: Stefan Negrea snegrea@redhat.com Date: Mon Aug 12 12:09:47 2013 -0500
One more attempt at the justification for the Server interface change.
diff --git a/modules/core/domain/intentional-api-changes-since-4.8.0.xml b/modules/core/domain/intentional-api-changes-since-4.8.0.xml index 6630d2c..b14d38e 100644 --- a/modules/core/domain/intentional-api-changes-since-4.8.0.xml +++ b/modules/core/domain/intentional-api-changes-since-4.8.0.xml @@ -11,7 +11,7 @@ <difference> <className>org/rhq/core/domain/cloud/Server</className> <differenceType>7004</differenceType><!-- num argments changed --> - <method>clearStatus(*)</method> + <method>clearStatus()</method> <justification> This class is not exposed remotely. The previous method signature was doing a blind clear of the status. The new method will clear only the specified status.
commit 2bd4941850a6f6a9daccd636eafd6d8cc9b0dbde Author: Stefan Negrea snegrea@redhat.com Date: Mon Aug 12 12:09:10 2013 -0500
Update code related to initial value of status field. Also, reserved the first five bits of the bitmask for debug purposes.
Because the field was initialized to -1 it was wrongly computing flags during startup resulting in a false manual maintenance mode.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java index caeabcf..7fa82f7 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java @@ -49,7 +49,7 @@ import org.rhq.core.domain.resource.Agent;
/** * An RHQ server node in the cluster - * + * * @author Joseph Marques */ @Entity(name = "Server") @@ -88,7 +88,9 @@ import org.rhq.core.domain.resource.Agent; + " AND ( s.name <> :thisServerName OR :thisServerName IS NULL ) "), // @NamedQuery(name = Server.QUERY_UPDATE_STATUS_BY_NAME, query = "" // + " UPDATE Server s " // - + " SET s.status = -1 " // negative numbers so that bitmask strat does not conflict with this one + + " SET s.status = 3 " //change this to the only value possible before adding MANUAL_MAINTENANCE_MODE + //this status should never be set to negative numbers since they are values allowed + //by the bitmask. + " WHERE s.status = 0 ") }) @SequenceGenerator(allocationSize = org.rhq.core.domain.util.Constants.ALLOCATION_SIZE, name = "RHQ_SERVER_ID_SEQ", sequenceName = "RHQ_SERVER_ID_SEQ") @Table(name = "RHQ_SERVER") @@ -276,7 +278,7 @@ public class Server implements Serializable { /** * Returns 0 if this server is current. Otherwise, returns a mask of {@link Server.Status} * elements corresponding to the updates that have occurred that are related to this server. - * + * * @return 0 if this server is current. Otherwise, returns a mask of {@link Server.Status} * elements corresponding to the updates that have occurred that are related to this server. */ @@ -320,11 +322,17 @@ public class Server implements Serializable { return Status.getMessages(status); }
+ //Please read BZ 535484 for initial design: https://bugzilla.redhat.com/show_bug.cgi?id=535484 + //Prior to MANUAL_MAINTENANCE_MODE only used for debug purposes, design now changed to + //persist statuses between server restarts in production code public enum Status {
+ //Debug only flags (first five bits are reserved for debug flags) RESOURCE_HIERARCHY_UPDATED(1, "The resource hierarchy has been updated"), // ALERT_DEFINITION(2, "Some alert definition with a global condition category was updated"), - MANUAL_MAINTENANCE_MODE(4,"Manual Maintenance mode setup by the user either via UI or properties file."); + + //Production flags + MANUAL_MAINTENANCE_MODE(32, "Manual Maintenance mode setup by the user either via UI or properties file.");
public final int mask; public final String message;
commit 86497c50fa4a2b79836525b6111c7182087f0815 Author: Mike Thompson mithomps@redhat.com Date: Fri Aug 9 14:00:58 2013 -0700
Fix graph labels for chrome & IE.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java index 3e573dd..64c355d 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/AvailabilityOverUnderGraphType.java @@ -260,8 +260,6 @@ public class AvailabilityOverUnderGraphType implements AvailabilityGraphType { .attr("fill", "#b0b0b0") .attr("stroke-width", "0.5") .attr("transform", "translate(0," + height + ")") - .attr("letter-spacing", "3") - .style("text-anchor", "end") .call(xAxis);
svg.append("text") @@ -296,6 +294,8 @@ public class AvailabilityOverUnderGraphType implements AvailabilityGraphType {
}
+ + function createHovers() { $wnd.jQuery('svg rect.availBars').tipsy({ gravity: 's', diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java index 67552d3..0c95f44 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/common/graph/graphtype/StackedBarMetricGraphImpl.java @@ -469,8 +469,6 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph { svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") - .attr("letter-spacing", "3") - .style("text-anchor", "end") .call(xAxis);
@@ -481,7 +479,6 @@ public class StackedBarMetricGraphImpl extends AbstractMetricGraph { .append("text") .attr("transform", "rotate(-90),translate( -60,0)") .attr("y", -30) - .attr("letter-spacing", "3") .style("text-anchor", "end") .text(chartContext.yAxisUnits === "NONE" ? "" : chartContext.yAxisUnits);
commit e3efeb22868e1b9d7b898194242d9cdbda44c787 Author: John Mazzitelli mazz@redhat.com Date: Fri Aug 16 15:11:40 2013 -0400
indicate unassigned group is not a real group - don't allow user to click its node. deselect any tree node when going to the main #Bundle URL.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java index 5ec6401..b46ce74 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java @@ -321,6 +321,9 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { node.setID(String.valueOf(bundleGroup.getId())); node.setName(StringUtility.escapeHtml(bundleGroup.getName()));
+ if (bundleGroup.getId() == 0) { + node.setEnabled(false); + } } else if (from instanceof Bundle) { Bundle bundle = (Bundle) from; node.setIsFolder(true); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java index 25ec7e7..7534ed0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java @@ -163,8 +163,6 @@ public class BundleTreeView extends TreeGrid { }); } else { deselectAllRecords(); - if (getTotalRows() > 0) - selectRecord(0); } }
commit 34c7908b0478358025d790f8a9cb1cc59da70e27 Author: John Mazzitelli mazz@redhat.com Date: Thu Aug 15 17:48:45 2013 -0400
refactor out the unused/obslete constructors that take multiple header icons
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java index 0aa613f..a2cea63 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java @@ -83,6 +83,8 @@ public enum IconEnum { BUNDLE_GROUP("subsystems/bundle/BundleGroup_16.png", "subsystems/bundle/BundleGroup_24.png"), BUNDLE_DELETE("subsystems/bundle/BundleAction_Delete_16.png", "subsystems/bundle/BundleAction_Delete_24.png"), BUNDLE_DEPLOY("subsystems/bundle/BundleAction_Deploy_16.png", "subsystems/bundle/BundleAction_Deploy_24.png"), + BUNDLE_VERSION("subsystems/bundle/BundleVersion_16.png", "subsystems/bundle/BundleVersion_24.png"), + BUNDLE_DEPLOYMENT("subsystems/bundle/BundleDeployment_16.png", "subsystems/bundle/BundleDeployment_24.png"), BUNDLE_DESTINATION("subsystems/bundle/BundleDestination_16.png", "subsystems/bundle/BundleDestination_24.png"), BUNDLE_DESTINATION_DELETE("subsystems/bundle/BundleDestinationAction_Delete_16.png", "subsystems/bundle/BundleDestinationAction_Delete_24.png"), BUNDLE_DESTINATION_PURGE("subsystems/bundle/BundleDestinationAction_Purge_16.png", "subsystems/bundle/BundleDestinationAction_Purge_24.png"), diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java index 1f5a360..4a7488f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentListView.java @@ -39,6 +39,7 @@ import com.smartgwt.client.widgets.grid.events.RecordClickHandler; import org.rhq.core.domain.bundle.BundleDeploymentStatus; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.ErrorMessageWindow; +import org.rhq.enterprise.gui.coregui.client.IconEnum; import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.bundle.list.BundleVersionDataSource; import org.rhq.enterprise.gui.coregui.client.components.table.EscapedHtmlCellFormatter; @@ -54,10 +55,9 @@ public class BundleDeploymentListView extends Table<BundleDeploymentDataSource> private final boolean canManageBundles;
public BundleDeploymentListView(Criteria criteria, boolean canManageBundles) { - super(MSG.view_bundle_bundleDeployments(), criteria); + super(MSG.view_bundle_bundleDeployments(), criteria, IconEnum.BUNDLE_DEPLOYMENT.getIcon24x24Path()); this.canManageBundles = canManageBundles; setDataSource(new BundleDeploymentDataSource()); - setHeaderIcon("subsystems/bundle/BundleDeployment_24.png"); }
@Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java index 1adbc68..05e7e2c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java @@ -35,6 +35,7 @@ import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.bundle.BundleDeploymentStatus; import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.IconEnum; import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.components.table.Table; import org.rhq.enterprise.gui.coregui.client.components.table.TimestampCellFormatter; @@ -50,8 +51,7 @@ public class BundleDestinationListView extends Table<BundleDestinationDataSource }
public BundleDestinationListView(Criteria criteria) { - super(MSG.view_bundle_bundleDestinations(), criteria); - setHeaderIcon("subsystems/bundle/BundleDestination_24.png"); + super(MSG.view_bundle_bundleDestinations(), criteria, IconEnum.BUNDLE_DESTINATION.getIcon24x24Path()); setDataSource(new BundleDestinationDataSource()); }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionListView.java index 25e0daf..6dbe5e6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionListView.java @@ -32,6 +32,7 @@ import com.smartgwt.client.widgets.grid.ListGridField; import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.IconEnum; import org.rhq.enterprise.gui.coregui.client.LinkManager; import org.rhq.enterprise.gui.coregui.client.bundle.list.BundleVersionDataSource; import org.rhq.enterprise.gui.coregui.client.components.table.Table; @@ -46,8 +47,7 @@ public class BundleVersionListView extends Table<BundleVersionDataSource> { }
public BundleVersionListView(Criteria criteria) { - super(MSG.view_bundle_bundleVersions(), criteria); - setHeaderIcon("subsystems/bundle/BundleVersion_24.png"); + super(MSG.view_bundle_bundleVersions(), criteria, IconEnum.BUNDLE_VERSION.getIcon24x24Path()); setDataSource(new BundleVersionDataSource()); }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java index 0036dfc..9aeef30 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/components/table/Table.java @@ -1067,17 +1067,6 @@ public class Table<DS extends RPCDataSource> extends EnhancedHLayout implements this.extraWidgetsAtTop.add(widget); }
- public void setHeaderIcon(String headerIcon) { - if (this.headerIcons.size() > 0) { - this.headerIcons.clear(); - } - addHeaderIcon(headerIcon); - } - - public void addHeaderIcon(String headerIcon) { - this.headerIcons.add(headerIcon); - } - /** * By default, all table actions have buttons that are enabled or * disabled based on if and how many rows are selected. There are diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/FavoriteGroupsPortlet.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/FavoriteGroupsPortlet.java index bf082b2..b78bbe6 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/FavoriteGroupsPortlet.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/dashboard/portlets/groups/FavoriteGroupsPortlet.java @@ -60,7 +60,7 @@ public class FavoriteGroupsPortlet extends ResourceGroupListView implements Auto private Timer refreshTimer;
public FavoriteGroupsPortlet() { - super(createInitialCriteria(), NAME); + super(createInitialCriteria(), NAME, null); setOverflow(Overflow.VISIBLE);
setShowHeader(false); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/InventoryView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/InventoryView.java index 81fef22..6f9a2ac 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/InventoryView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/InventoryView.java @@ -33,7 +33,6 @@ import org.rhq.core.domain.resource.InventoryStatus; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.group.GroupCategory; import org.rhq.enterprise.gui.coregui.client.IconEnum; -import org.rhq.enterprise.gui.coregui.client.ImageManager; import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener; import org.rhq.enterprise.gui.coregui.client.PermissionsLoader; import org.rhq.enterprise.gui.coregui.client.components.TitleBar; @@ -157,10 +156,7 @@ public class InventoryView extends AbstractSectionedLeftNavigationView {
NavigationItem allResourcesItem = new NavigationItem(PAGE_ALL_RESOURCES, new ViewFactory() { public Canvas createView() { - return new ResourceSearchViewWrapper(PAGE_ALL_RESOURCES, null, - ImageManager.getResourceLargeIcon(ResourceCategory.PLATFORM), - ImageManager.getResourceLargeIcon(ResourceCategory.SERVER), - ImageManager.getResourceLargeIcon(ResourceCategory.SERVICE)); + return new ResourceSearchViewWrapper(PAGE_ALL_RESOURCES, null, null); } });
@@ -272,13 +268,13 @@ public class InventoryView extends AbstractSectionedLeftNavigationView { private final boolean showIgnoreButton; private final boolean showUnignoreButton;
- public ResourceSearchViewWrapper(ViewName viewName, Criteria criteria, String... headerIcons) { - this(true, false, viewName, criteria, headerIcons); + public ResourceSearchViewWrapper(ViewName viewName, Criteria criteria, String headerIcon) { + this(true, false, viewName, criteria, headerIcon); }
public ResourceSearchViewWrapper(boolean showIgnoredButton, boolean showUnignoreButton, ViewName viewName, - Criteria criteria, String... headerIcons) { - super(criteria, viewName.getTitle(), headerIcons); + Criteria criteria, String headerIcon) { + super(criteria, viewName.getTitle(), headerIcon); this.viewName = viewName; this.showIgnoreButton = showIgnoredButton; this.showUnignoreButton = showUnignoreButton; 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 dfba2cb..d71988b 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 @@ -71,7 +71,7 @@ public abstract class AbstractOperationHistoryListView<T extends AbstractOperati public AbstractOperationHistoryListView(T dataSource, String title) { super(title); setDataSource(dataSource); - setHeaderIcon(HEADER_ICON); + setTitleIcon(HEADER_ICON); }
public AbstractOperationHistoryListView(T dataSource, String title, Criteria criteria) { diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupListView.java index 846f8e9..548ab83 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/ResourceGroupListView.java @@ -79,14 +79,14 @@ public class ResourceGroupListView extends Table<ResourceGroupCompositeDataSourc }
public ResourceGroupListView(String title) { - this(null, title); + this(null, title, null); }
- public ResourceGroupListView(Criteria criteria, String title, String... headerIcons) { + public ResourceGroupListView(Criteria criteria, String title, String headerIcon) { super(title, criteria);
- for (String headerIcon : headerIcons) { - addHeaderIcon(headerIcon); + if (headerIcon != null) { + setTitleIcon(headerIcon); }
final ResourceGroupCompositeDataSource datasource = ResourceGroupCompositeDataSource.getInstance(); @@ -273,7 +273,7 @@ public class ResourceGroupListView extends Table<ResourceGroupCompositeDataSourc public static ResourceGroupListView getGroupsOf(int explicitResourceId, boolean canModifyMembership) {
ResourceGroupListView view = new ResourceGroupListView(new Criteria("explicitResourceId", - String.valueOf(explicitResourceId)), MSG.common_title_resourceGroups()); + String.valueOf(explicitResourceId)), MSG.common_title_resourceGroups(), null); if (canModifyMembership) { view.resourceIdToModify = Integer.valueOf(explicitResourceId); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/MembersView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/MembersView.java index f246d79..f6c64f8 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/MembersView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/groups/detail/inventory/MembersView.java @@ -47,7 +47,7 @@ public class MembersView extends ResourceSearchView {
public MembersView(int groupId, boolean canModifyMembers) { super(new Criteria(ResourceDatasource.FILTER_GROUP_ID, String.valueOf(groupId)), MSG - .view_inventory_resources_members()); + .view_inventory_resources_members(), null); setInitialCriteriaFixed(true); this.canModifyMembers = canModifyMembers; this.groupId = groupId; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java index aa9feb0..d9f16d7 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java @@ -72,16 +72,16 @@ public class ResourceCompositeSearchView extends ResourceSearchView { private boolean canCreate;
public ResourceCompositeSearchView(ResourceComposite parentResourceComposite, Criteria criteria, String title, - SortSpecifier[] sortSpecifier, String[] excludeFields, String... headerIcons) { - super(criteria, title, sortSpecifier, excludeFields, headerIcons); + SortSpecifier[] sortSpecifier, String[] excludeFields, String headerIcon) { + super(criteria, title, sortSpecifier, excludeFields, headerIcon); this.parentResourceComposite = parentResourceComposite; this.canCreate = this.parentResourceComposite.getResourcePermission().isCreateChildResources(); setInitialCriteriaFixed(true); }
public ResourceCompositeSearchView(ResourceComposite parentResourceComposite, Criteria criteria, String title, - String... headerIcons) { - this(parentResourceComposite, criteria, title, null, null, headerIcons); + String headerIcon) { + this(parentResourceComposite, criteria, title, null, null, headerIcon); }
@Override @@ -381,7 +381,7 @@ public class ResourceCompositeSearchView extends ResourceSearchView {
public static ResourceCompositeSearchView getChildrenOf(ResourceComposite parentResourceComposite) { return new ResourceCompositeSearchView(parentResourceComposite, new Criteria("parentId", - String.valueOf(parentResourceComposite.getResource().getId())), MSG.view_tabs_common_child_resources()); + String.valueOf(parentResourceComposite.getResource().getId())), MSG.view_tabs_common_child_resources(), null); }
@Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java index c24c485..e55aed7 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceSearchView.java @@ -101,58 +101,58 @@ public class ResourceSearchView extends Table { * A list of all Resources in the system. */ public ResourceSearchView() { - this(null, null, null, null, false); + this(null, null, null, null, false, null); }
/** * A Resource list filtered by a given criteria. */ public ResourceSearchView(Criteria criteria) { - this(criteria, null, null, null, false); + this(criteria, null, null, null, false, null); }
/** * A Resource list filtered by a given criteria and optionally exportable */ public ResourceSearchView(Criteria criteria, boolean exportable) { - this(criteria, null, null, null, exportable); + this(criteria, null, null, null, exportable, null); }
/** * A Resource list filtered by a given criteria with the given title. * - * @param headerIcons 24x24 icon(s) to be displayed in the header + * @param headerIcon */ - public ResourceSearchView(Criteria criteria, String title, String... headerIcons) { - this(criteria, title, null, null, false, headerIcons); + public ResourceSearchView(Criteria criteria, String title, String headerIcon) { + this(criteria, title, null, null, false, headerIcon); }
/** * A Resource list filtered by a given criteria with the given title. * - * @param headerIcons 24x24 icon(s) to be displayed in the header + * @param headerIcon */ public ResourceSearchView(Criteria criteria, String title, SortSpecifier[] sortSpecifier, String[] excludeFields, - String... headerIcons) { + String headerIcon) {
- this(criteria, title, sortSpecifier, excludeFields, false, headerIcons); + this(criteria, title, sortSpecifier, excludeFields, false, headerIcon); }
/** * A Resource list filtered by a given criteria with the given title and optionally exportable. * - * @param headerIcons 24x24 icon(s) to be displayed in the header + * @param headerIcon */ public ResourceSearchView(Criteria criteria, String title, SortSpecifier[] sortSpecifier, String[] excludeFields, - boolean exportable, String... headerIcons) { + boolean exportable, String headerIcon) {
super((null == title) ? DEFAULT_TITLE : title, criteria, (null == sortSpecifier) ? DEFAULT_SORT_SPECIFIER : sortSpecifier, excludeFields);
this.exportable = exportable;
- for (String headerIcon : headerIcons) { - addHeaderIcon(headerIcon); + if (headerIcon != null) { + setTitleIcon(headerIcon); }
final RPCDataSource<Resource, ResourceCriteria> datasource = getDataSourceInstance(); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java index 9aa5297..8a12f5a 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java @@ -147,7 +147,7 @@ public class TaggedView extends EnhancedVLayout implements BookmarkableView, Has tab.setPane(bundleDestinationListView); container.addTab(tab);
- ResourceSearchView resourceView = new ResourceSearchView(criteria, MSG.view_taggedResources_title()); + ResourceSearchView resourceView = new ResourceSearchView(criteria, MSG.view_taggedResources_title(), null); viewsWithTags.add(resourceView); tab = new Tab(MSG.view_taggedResources_title()); tab.setIcon(ImageManager.getResourceIcon(ResourceCategory.SERVICE));
commit 215ec0eaab5de9f4dcf894f0a4d4067ef196bfb8 Author: John Mazzitelli mazz@redhat.com Date: Thu Aug 15 15:56:40 2013 -0400
fix some more bundle view stuff
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java index f1400ee..c999565 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java @@ -117,6 +117,7 @@ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGro //criteria.addFilterTagName(getFilter(request, "tagName", String.class)); //criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
+ criteria.addFilterId(getFilter(request, FIELD_ID, Integer.class)); criteria.addFilterName(getFilter(request, "search", String.class)); criteria.addFilterBundleIds(getArrayFilter(request, "bundleIds", Integer.class)); criteria.fetchBundles(true); @@ -192,7 +193,7 @@ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGro record.setAttribute(FIELD_ID, from.getId()); record.setAttribute(FIELD_NAME, from.getName()); record.setAttribute(FIELD_NAMELINK, LinkManager.getBundleGroupLink(from.getId())); - record.setAttribute(FIELD_DESCRIPTION, from.getDescription()); + record.setAttribute(FIELD_DESCRIPTION, (from.getDescription() == null) ? "" : from.getDescription());
if (cascade) { Set<Bundle> bundles = from.getBundles(); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java index 8fb2c08..a6e4718 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java @@ -74,7 +74,7 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i public BundleGroupsListView(Criteria criteria, Set<Permission> globalpermissions) { super(MSG.common_title_bundleGroups(), criteria); this.globalPermissions = (null != globalpermissions) ? globalpermissions : new HashSet<Permission>(); - setHeaderIcon(IconEnum.BUNDLE_GROUP.getIcon24x24Path()); + setTitleIcon(IconEnum.BUNDLE_GROUP.getIcon24x24Path()); setDataSource(new BundleGroupsDataSource()); }
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java index d8b66c8..50ca139 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java @@ -75,7 +75,6 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> { public BundlesListView(Criteria criteria, Set<Permission> perms) { super(MSG.common_title_bundles(), criteria, IconEnum.BUNDLE.getIcon24x24Path()); this.permissions = perms; - setHeaderIcon(IconEnum.BUNDLE.getIcon24x24Path()); setDataSource(new BundlesWithLatestVersionDataSource()); }
commit bddf7c52f70ba85d4b7078a7572c8a7575576bd2 Author: John Mazzitelli mazz@redhat.com Date: Thu Aug 15 14:02:23 2013 -0400
more fixes to the bundle tree. almost got it working fully
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java index d7f0220..5ec6401 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java @@ -344,7 +344,7 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { node.setIcon("subsystems/bundle/BundleDeployment_16.png"); parentID = bundleGroupId.toString() + "_" + bundleId + "_destinations_" + deployment.getDestination().getId(); node.setParentID(parentID); - node.setID(bundleId + "_deployments_" + deployment.getId()); + node.setID(bundleGroupId.toString() + "_" + bundleId + "_deployments_" + deployment.getId()); String name = StringUtility.escapeHtml(deployment.getName()); if (deployment.isLive()) { node.setName("<span style="color: green; font-weight: bold">(live)</span> " + name); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java index a6f7d7e..25ec7e7 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java @@ -112,7 +112,7 @@ public class BundleTreeView extends TreeGrid { if (key.length() > 0) { key += "_"; } else { - key = String.valueOf(currentlySelectedBundleGroupId); // all keys start with the parent group ID + key = String.valueOf(currentlySelectedBundleGroupId) + '_'; // all keys start with the parent group ID }
key += view.getPath();
commit 9694dc3f0030514c1bb1c8abaad53576c4b84dc1 Author: John Mazzitelli mazz@redhat.com Date: Thu Aug 15 13:06:39 2013 -0400
fix the selection of group node make the name of the unassigned group stand out to show that its "special"
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java index df01fda..a6f7d7e 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java @@ -79,7 +79,7 @@ public class BundleTreeView extends TreeGrid { }
if (splitPath.length == 1) { - CoreGUI.goToView("Bundles"); + CoreGUI.goToView("Bundles/BundleGroup/" + currentlySelectedBundleGroupId); } else { CoreGUI.goToView("Bundles/Bundle/" + splitPath[1]); } @@ -109,8 +109,11 @@ public class BundleTreeView extends TreeGrid { if (viewPath.viewsLeft() > 0) { String key = ""; for (ViewId view : viewPath.getViewPath().subList(2, viewPath.getViewPath().size())) { - if (key.length() > 0) + if (key.length() > 0) { key += "_"; + } else { + key = String.valueOf(currentlySelectedBundleGroupId); // all keys start with the parent group ID + }
key += view.getPath();
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 b2f7cb7..8f9fe56 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 @@ -1363,7 +1363,7 @@ view_bundle_revertWizard_title = Bundle Revert view_bundle_revertWizard_windowTitle = Bundle Revert Wizard view_bundle_tree_loadFailure = Failed to load bundle data view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -view_bundle_tree_unassigned_name = Unassigned Bundles +view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = Back to Bundle view_bundle_version_bundleVersionTagUpdateFailure = Failed to update bundle version tags view_bundle_version_bundleVersionTagUpdateSuccessful = You have successfully updated the bundle version tags diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index d69077e..a71ddd1 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -1376,7 +1376,7 @@ view_bundle_revertWizard_title = Vrácení balíku view_bundle_revertWizard_windowTitle = Průvodce vrácení balíku view_bundle_tree_loadFailure = Nepodařilo se načíst data balíku ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = Zpět na balík view_bundle_version_bundleVersionTagUpdateFailure = Nepodařilo se změnit tagy pro verzi balíku view_bundle_version_bundleVersionTagUpdateSuccessful = Úspěšně jste změnili tagy pro verzi balíku diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index ea61495..d85b08e 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -1267,7 +1267,7 @@ view_bundle_revert = Zurückrollen ##view_bundle_revertWizard_windowTitle = Bundle Revert Wizard ##view_bundle_tree_loadFailure = Failed to load bundle data ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = Zurück zum Bundle ##view_bundle_version_bundleVersionTagUpdateFailure = Failed to update bundle version tags ##view_bundle_version_bundleVersionTagUpdateSuccessful = You have successfully updated the bundle version tags diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index 135fabe..f5dc83b 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -1354,7 +1354,7 @@ view_bundle_revertWizard_title = バンドル取り消し view_bundle_revertWizard_windowTitle = バンドル取り消しウィザード view_bundle_tree_loadFailure = バンドルデータのロードに失敗しました ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = バンドルへ戻る view_bundle_version_bundleVersionTagUpdateFailure = バンドルバージョンタグの更新に失敗しました view_bundle_version_bundleVersionTagUpdateSuccessful = バンドルバージョンタグの更新に成功しました diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index 4eaaf89..7fc1609 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -1204,7 +1204,7 @@ view_bundle_revertWizard_title = 번들 취소 view_bundle_revertWizard_windowTitle = 번들 취소 마법사 view_bundle_tree_loadFailure = 번들 데이터 로드에 실패했습니다 ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = 뒤로 가기 view_bundle_version_deleteFailure = 번들 버전 [{0}]을 삭제하는데 실패했습니다 view_bundle_version_deleteSuccessful = 번들 버전 [{0}]을 삭제하는데 성공했습니다 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index 13f31e9..611c641 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -1365,7 +1365,7 @@ view_bundle_revertWizard_title = Revers\u00E3o do Bundle view_bundle_revertWizard_windowTitle = Assistente de revers\u00E3o do Bundle view_bundle_tree_loadFailure = Falha ao carregar dados do Bundle ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = Retornar ao Bundle view_bundle_version_bundleVersionTagUpdateFailure = Falha ao atualizar as tags da vers\u00E3o do bundle view_bundle_version_bundleVersionTagUpdateSuccessful = Tags da vers\u00E3o do bundle atualizadas com sucesso! diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index 43d278b..bae4916 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2762,7 +2762,7 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль ##view_bundle_list_deletesSuccessful = You successfully deleted the bundles ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1} ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* ##view_configEdit_description = Description ##view_configEdit_property = Vlastnost ##view_configEdit_unset = Unset? diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index c304310..2bcd8fc 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -1350,7 +1350,7 @@ view_bundle_revertWizard_title = Bundle\u8fd8\u539f view_bundle_revertWizard_windowTitle = Bundle\u8fd8\u539f\u5411\u5bfc view_bundle_tree_loadFailure = \u52a0\u8f7dbundle\u6570\u636e\u5931\u8d25 ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Bundles +##view_bundle_tree_unassigned_name = *Unassigned Bundles* view_bundle_version_backToBundle = \u8fd4\u56deBundle view_bundle_version_bundleVersionTagUpdateFailure = \u66f4\u65b0bundle\u7248\u672c\u6807\u8bb0\u5931\u8d25 view_bundle_version_bundleVersionTagUpdateSuccessful = \u66f4\u65b0bundle\u7248\u672c\u6807\u8bb0\u6210\u529f
commit 7b73325c5faeda787148f4b3ea6e0e6cdec95640 Author: John Mazzitelli mazz@redhat.com Date: Thu Aug 15 11:38:06 2013 -0400
fix the i18n value to something more meaningful
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 15af496..b2f7cb7 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 @@ -1363,7 +1363,7 @@ view_bundle_revertWizard_title = Bundle Revert view_bundle_revertWizard_windowTitle = Bundle Revert Wizard view_bundle_tree_loadFailure = Failed to load bundle data view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -view_bundle_tree_unassigned_name = Unassigned Name +view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = Back to Bundle view_bundle_version_bundleVersionTagUpdateFailure = Failed to update bundle version tags view_bundle_version_bundleVersionTagUpdateSuccessful = You have successfully updated the bundle version tags diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index a7b5903..d69077e 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -1376,7 +1376,7 @@ view_bundle_revertWizard_title = Vrácení balíku view_bundle_revertWizard_windowTitle = Průvodce vrácení balíku view_bundle_tree_loadFailure = Nepodařilo se načíst data balíku ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = Zpět na balík view_bundle_version_bundleVersionTagUpdateFailure = Nepodařilo se změnit tagy pro verzi balíku view_bundle_version_bundleVersionTagUpdateSuccessful = Úspěšně jste změnili tagy pro verzi balíku diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index 658588f..ea61495 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -1267,7 +1267,7 @@ view_bundle_revert = Zurückrollen ##view_bundle_revertWizard_windowTitle = Bundle Revert Wizard ##view_bundle_tree_loadFailure = Failed to load bundle data ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = Zurück zum Bundle ##view_bundle_version_bundleVersionTagUpdateFailure = Failed to update bundle version tags ##view_bundle_version_bundleVersionTagUpdateSuccessful = You have successfully updated the bundle version tags diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index 5fedff7..135fabe 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -1354,7 +1354,7 @@ view_bundle_revertWizard_title = バンドル取り消し view_bundle_revertWizard_windowTitle = バンドル取り消しウィザード view_bundle_tree_loadFailure = バンドルデータのロードに失敗しました ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = バンドルへ戻る view_bundle_version_bundleVersionTagUpdateFailure = バンドルバージョンタグの更新に失敗しました view_bundle_version_bundleVersionTagUpdateSuccessful = バンドルバージョンタグの更新に成功しました diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index 72b02ed..4eaaf89 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -1204,7 +1204,7 @@ view_bundle_revertWizard_title = 번들 취소 view_bundle_revertWizard_windowTitle = 번들 취소 마법사 view_bundle_tree_loadFailure = 번들 데이터 로드에 실패했습니다 ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = 뒤로 가기 view_bundle_version_deleteFailure = 번들 버전 [{0}]을 삭제하는데 실패했습니다 view_bundle_version_deleteSuccessful = 번들 버전 [{0}]을 삭제하는데 성공했습니다 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index bf49b55..13f31e9 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -1365,7 +1365,7 @@ view_bundle_revertWizard_title = Revers\u00E3o do Bundle view_bundle_revertWizard_windowTitle = Assistente de revers\u00E3o do Bundle view_bundle_tree_loadFailure = Falha ao carregar dados do Bundle ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = Retornar ao Bundle view_bundle_version_bundleVersionTagUpdateFailure = Falha ao atualizar as tags da vers\u00E3o do bundle view_bundle_version_bundleVersionTagUpdateSuccessful = Tags da vers\u00E3o do bundle atualizadas com sucesso! diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index 8c82393..43d278b 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2762,7 +2762,7 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль ##view_bundle_list_deletesSuccessful = You successfully deleted the bundles ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1} ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles ##view_configEdit_description = Description ##view_configEdit_property = Vlastnost ##view_configEdit_unset = Unset? diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index fa98ec0..c304310 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -1350,7 +1350,7 @@ view_bundle_revertWizard_title = Bundle\u8fd8\u539f view_bundle_revertWizard_windowTitle = Bundle\u8fd8\u539f\u5411\u5bfc view_bundle_tree_loadFailure = \u52a0\u8f7dbundle\u6570\u636e\u5931\u8d25 ##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. -##view_bundle_tree_unassigned_name = Unassigned Name +##view_bundle_tree_unassigned_name = Unassigned Bundles view_bundle_version_backToBundle = \u8fd4\u56deBundle view_bundle_version_bundleVersionTagUpdateFailure = \u66f4\u65b0bundle\u7248\u672c\u6807\u8bb0\u5931\u8d25 view_bundle_version_bundleVersionTagUpdateSuccessful = \u66f4\u65b0bundle\u7248\u672c\u6807\u8bb0\u6210\u529f
commit 3ce64fa6a61dd3e0bea692bbc7737caf05d885c1 Author: John Mazzitelli mazz@redhat.com Date: Thu Aug 15 11:31:11 2013 -0400
i18n the unassigned tree node label
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java index fbfa34c..d7f0220 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java @@ -109,8 +109,8 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { public void onSuccess(PageList<Bundle> result) { BundleGroup unassignedBundleGroup = new BundleGroup(); unassignedBundleGroup.setId(0); // ID=0 is an indicator we use to denote the unassigned group - unassignedBundleGroup.setName("TODO i18n Unassigned Bundles"); - unassignedBundleGroup.setDescription("TODO i18n These are bundles that are not assigned to any bundle group."); + unassignedBundleGroup.setName(MSG.view_bundle_tree_unassigned_name()); + unassignedBundleGroup.setDescription(MSG.view_bundle_tree_unassigned_desc());
// Because findBundleGroupsByCriteria would not have given us all unassigned bundles, we used // findBundlesByCriteria. But we need to organize our tree structure with groups at the top, so 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 6f6e30e..15af496 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 @@ -1362,6 +1362,8 @@ view_bundle_revertWizard_revertStep_scheduledFailure = Failed to schedule revert view_bundle_revertWizard_title = Bundle Revert view_bundle_revertWizard_windowTitle = Bundle Revert Wizard view_bundle_tree_loadFailure = Failed to load bundle data +view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = Back to Bundle view_bundle_version_bundleVersionTagUpdateFailure = Failed to update bundle version tags view_bundle_version_bundleVersionTagUpdateSuccessful = You have successfully updated the bundle version tags diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index 72c70a3..a7b5903 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -1375,6 +1375,8 @@ view_bundle_revertWizard_revertStep_scheduledFailure = Nepodařilo se naplánova view_bundle_revertWizard_title = Vrácení balíku view_bundle_revertWizard_windowTitle = Průvodce vrácení balíku view_bundle_tree_loadFailure = Nepodařilo se načíst data balíku +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = Zpět na balík view_bundle_version_bundleVersionTagUpdateFailure = Nepodařilo se změnit tagy pro verzi balíku view_bundle_version_bundleVersionTagUpdateSuccessful = Úspěšně jste změnili tagy pro verzi balíku diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index 099c61e..658588f 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -1266,6 +1266,8 @@ view_bundle_revert = Zurückrollen ##view_bundle_revertWizard_title = Bundle Revert ##view_bundle_revertWizard_windowTitle = Bundle Revert Wizard ##view_bundle_tree_loadFailure = Failed to load bundle data +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = Zurück zum Bundle ##view_bundle_version_bundleVersionTagUpdateFailure = Failed to update bundle version tags ##view_bundle_version_bundleVersionTagUpdateSuccessful = You have successfully updated the bundle version tags diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index 64f8f3d..5fedff7 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -1353,6 +1353,8 @@ view_bundle_revertWizard_revertStep_scheduledFailure = デプロイの取り消 view_bundle_revertWizard_title = バンドル取り消し view_bundle_revertWizard_windowTitle = バンドル取り消しウィザード view_bundle_tree_loadFailure = バンドルデータのロードに失敗しました +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = バンドルへ戻る view_bundle_version_bundleVersionTagUpdateFailure = バンドルバージョンタグの更新に失敗しました view_bundle_version_bundleVersionTagUpdateSuccessful = バンドルバージョンタグの更新に成功しました diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index c23a937..72b02ed 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -1203,6 +1203,8 @@ view_bundle_revertWizard_revertStep_scheduledFailure = 배포 취소 일정에 view_bundle_revertWizard_title = 번들 취소 view_bundle_revertWizard_windowTitle = 번들 취소 마법사 view_bundle_tree_loadFailure = 번들 데이터 로드에 실패했습니다 +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = 뒤로 가기 view_bundle_version_deleteFailure = 번들 버전 [{0}]을 삭제하는데 실패했습니다 view_bundle_version_deleteSuccessful = 번들 버전 [{0}]을 삭제하는데 성공했습니다 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index 37b3277..bf49b55 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -1364,6 +1364,8 @@ view_bundle_revertWizard_revertStep_scheduledFailure = Falha ao agendar a revers view_bundle_revertWizard_title = Revers\u00E3o do Bundle view_bundle_revertWizard_windowTitle = Assistente de revers\u00E3o do Bundle view_bundle_tree_loadFailure = Falha ao carregar dados do Bundle +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = Retornar ao Bundle view_bundle_version_bundleVersionTagUpdateFailure = Falha ao atualizar as tags da vers\u00E3o do bundle view_bundle_version_bundleVersionTagUpdateSuccessful = Tags da vers\u00E3o do bundle atualizadas com sucesso! diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index 6b44762..8c82393 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2761,6 +2761,8 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль ##view_bundle_list_deletesFailure = Failed to delete the bundles ##view_bundle_list_deletesSuccessful = You successfully deleted the bundles ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1} +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name ##view_configEdit_description = Description ##view_configEdit_property = Vlastnost ##view_configEdit_unset = Unset? diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index eb163d6..fa98ec0 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -1349,6 +1349,8 @@ view_bundle_revertWizard_revertStep_scheduledFailure = Failed to schedule revert view_bundle_revertWizard_title = Bundle\u8fd8\u539f view_bundle_revertWizard_windowTitle = Bundle\u8fd8\u539f\u5411\u5bfc view_bundle_tree_loadFailure = \u52a0\u8f7dbundle\u6570\u636e\u5931\u8d25 +##view_bundle_tree_unassigned_desc = These are bundles that are not yet associated with any bundle group. +##view_bundle_tree_unassigned_name = Unassigned Name view_bundle_version_backToBundle = \u8fd4\u56deBundle view_bundle_version_bundleVersionTagUpdateFailure = \u66f4\u65b0bundle\u7248\u672c\u6807\u8bb0\u5931\u8d25 view_bundle_version_bundleVersionTagUpdateSuccessful = \u66f4\u65b0bundle\u7248\u672c\u6807\u8bb0\u6210\u529f
commit d5cf338a0083ef6e57fd4f40c205e484966f6e60 Author: John Mazzitelli mazz@redhat.com Date: Wed Aug 14 17:30:53 2013 -0400
initial coding of the bundle left hand tree to support bundle groups. this is not fully complete yet, but is almost there.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java index 4cf3f0f..d232576 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java @@ -80,8 +80,7 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView { sectionStack.setHeight100();
SectionStackSection bundlesSection = new SectionStackSection(MSG.common_title_bundles()); - // TODO: Need to fix perm stuff in tree view - bundleTreeView = new BundleTreeView(true); + bundleTreeView = new BundleTreeView(); bundlesSection.addItem(bundleTreeView); sectionStack.addSection(bundlesSection);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java index 49e7f31..fbfa34c 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeDataSource.java @@ -24,7 +24,9 @@ package org.rhq.enterprise.gui.coregui.client.bundle.tree;
import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.DSRequest; @@ -38,6 +40,7 @@ import com.smartgwt.client.widgets.tree.TreeNode; import org.rhq.core.domain.bundle.Bundle; import org.rhq.core.domain.bundle.BundleDeployment; import org.rhq.core.domain.bundle.BundleDestination; +import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.criteria.BundleCriteria; import org.rhq.core.domain.criteria.BundleDeploymentCriteria; @@ -53,15 +56,14 @@ import org.rhq.enterprise.gui.coregui.client.util.StringUtility;
/** * @author Greg Hinkle + * @author John Mazzitelli */ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> {
- private BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService(); - private final boolean canManageBundles; + private final BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
- public BundleTreeDataSource(boolean canManageBundles) { + public BundleTreeDataSource() { super(); - this.canManageBundles = canManageBundles; List<DataSourceField> fields = addDataSourceFields(); addFields(fields); } @@ -88,14 +90,14 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { @Override protected void executeFetch(final DSRequest request, final DSResponse response, final Criteria unused) {
- String p = request.getCriteria().getAttribute("parentId"); + final String parentId = request.getCriteria().getAttribute("parentId");
- if (p == null) { + if (parentId == null) {
// there is no parent - we are at the root of the tree - // get the top nodes (the bundles) + // get the bundles and build the bundle groups (including unassigned) from that BundleCriteria criteria = new BundleCriteria(); - criteria.fetchDestinations(true); + criteria.fetchBundleGroups(true);
bundleService.findBundlesByCriteria(criteria, new AsyncCallback<PageList<Bundle>>() { public void onFailure(Throwable caught) { @@ -105,17 +107,54 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { }
public void onSuccess(PageList<Bundle> result) { - response.setData(buildRecords(result)); - response.setTotalRows(result.getTotalSize()); + BundleGroup unassignedBundleGroup = new BundleGroup(); + unassignedBundleGroup.setId(0); // ID=0 is an indicator we use to denote the unassigned group + unassignedBundleGroup.setName("TODO i18n Unassigned Bundles"); + unassignedBundleGroup.setDescription("TODO i18n These are bundles that are not assigned to any bundle group."); + + // Because findBundleGroupsByCriteria would not have given us all unassigned bundles, we used + // findBundlesByCriteria. But we need to organize our tree structure with groups at the top, so + // we need to put our results aggregated in groups. + HashMap<Integer, BundleGroup> visibleBundleGroups = new HashMap<Integer, BundleGroup>(); + for (Bundle bundle : result) { + Set<BundleGroup> bundleBundleGroups = bundle.getBundleGroups(); + if (bundleBundleGroups == null || bundleBundleGroups.isEmpty()) { + unassignedBundleGroup.addBundle(bundle); + } else { + for (BundleGroup bundleBundleGroup : bundleBundleGroups) { + BundleGroup theGroup = visibleBundleGroups.get(bundleBundleGroup.getId()); + if (theGroup == null) { + visibleBundleGroups.put(bundleBundleGroup.getId(), bundleBundleGroup); + theGroup = bundleBundleGroup; + } + theGroup.addBundle(bundle); + } + } + } + + ArrayList<BundleGroup> allVisibleBundleGroups = new ArrayList<BundleGroup>(visibleBundleGroups.values()); + if (!unassignedBundleGroup.getBundles().isEmpty()) { + allVisibleBundleGroups.add(unassignedBundleGroup); + } + response.setData(buildRecords(allVisibleBundleGroups)); + response.setTotalRows(allVisibleBundleGroups.size()); processResponse(request.getRequestId(), response); } });
} else { + String[] splitParentId = parentId.split("_", 3); // <bundleGroupId>_<bundleId>_<and the rest> + final Integer bundleGroupId = Integer.parseInt(splitParentId[0]); + Integer tmp; + try { + tmp = Integer.parseInt(splitParentId[1]); + } catch (NumberFormatException e) { + tmp = null; + } + final Integer bundleId = tmp;
// we are at an inner node, being asked to get the children of it - if (p.endsWith("_versions")) { - int bundleId = Integer.parseInt(p.substring(0, p.indexOf("_"))); + if (parentId.endsWith("_versions")) { BundleVersionCriteria criteria = new BundleVersionCriteria(); criteria.addFilterBundleId(bundleId); bundleService.findBundleVersionsByCriteria(criteria, new AsyncCallback<PageList<BundleVersion>>() { @@ -126,31 +165,29 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { }
public void onSuccess(PageList<BundleVersion> result) { - response.setData(buildRecords(result)); + response.setData(buildRecordsForKnownBundle(result, bundleGroupId, bundleId)); response.setTotalRows(result.getTotalSize()); processResponse(request.getRequestId(), response); } });
- } else if (p.endsWith("_deployments")) { - int bundleId = Integer.parseInt(p.substring(0, p.indexOf("_"))); + } else if (parentId.endsWith("_deployments")) { BundleDeploymentCriteria criteria = new BundleDeploymentCriteria(); criteria.fetchBundleVersion(true); criteria.addFilterBundleId(bundleId); bundleService.findBundleDeploymentsByCriteria(criteria, - new AsyncCallback<PageList<BundleDeployment>>() { - public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError(MSG.view_bundle_tree_loadFailure(), caught); - } - - public void onSuccess(PageList<BundleDeployment> result) { - response.setData(buildRecords(result)); - processResponse(request.getRequestId(), response); - } - }); - - } else if (p.endsWith("_destinations")) { - final int bundleId = Integer.parseInt(p.substring(0, p.indexOf("_"))); + new AsyncCallback<PageList<BundleDeployment>>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_tree_loadFailure(), caught); + } + + public void onSuccess(PageList<BundleDeployment> result) { + response.setData(buildRecordsForKnownBundle(result, bundleGroupId, bundleId)); + processResponse(request.getRequestId(), response); + } + }); + + } else if (parentId.endsWith("_destinations")) { BundleDestinationCriteria criteria = new BundleDestinationCriteria(); criteria.addFilterBundleId(bundleId); criteria.fetchDeployments(true); @@ -161,10 +198,29 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { }
public void onSuccess(PageList<BundleDestination> result) { - response.setData(buildRecordsForKnownBundle(result, bundleId)); + response.setData(buildRecordsForKnownBundle(result, bundleGroupId, bundleId)); processResponse(request.getRequestId(), response); } }); + } else { + // we are at a child node under a bundle node - its an individual destination or deployment node + BundleCriteria criteria = new BundleCriteria(); + criteria.addFilterId(bundleId); + criteria.fetchDestinations(true); + + bundleService.findBundlesByCriteria(criteria, new AsyncCallback<PageList<Bundle>>() { + public void onFailure(Throwable caught) { + CoreGUI.getErrorHandler().handleError(MSG.view_bundle_tree_loadFailure(), caught); + response.setStatus(DSResponse.STATUS_FAILURE); + processResponse(request.getRequestId(), response); + } + + public void onSuccess(PageList<Bundle> result) { + final ListGridRecord[] listGridRecordsData = buildRecordsForKnownBundle(result, bundleGroupId, bundleId); + response.setData(listGridRecordsData); + processResponse(request.getRequestId(), response); + } + }); } } } @@ -183,10 +239,10 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> {
@Override public ListGridRecord[] buildRecords(Collection dataObjects) { - return buildRecordsForKnownBundle(dataObjects, null); + return buildRecordsForKnownBundle(dataObjects, null, null); }
- public ListGridRecord[] buildRecordsForKnownBundle(Collection dataObjects, Integer bundleId) { + private ListGridRecord[] buildRecordsForKnownBundle(Collection dataObjects, Integer bundleGroupId, Integer bundleId) { if (dataObjects == null) { return null; } @@ -196,34 +252,53 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { for (Object item : dataObjects) {
// the resultant item is a direct node to build - records.add(copyValues(item)); + records.add(copyValuesForKnownBundle(item, bundleGroupId, bundleId));
// now build the children of the node - if (item instanceof Bundle) { + if (item instanceof BundleGroup) { + BundleGroup bundleGroup = (BundleGroup) item; + Set<Bundle> bundles = bundleGroup.getBundles(); + if (bundles != null) { + for (Bundle bundle : bundles) { + records.add(copyValuesForKnownBundle(bundle, bundleGroup.getId(), bundle.getId())); + // while we are here, automatically add the two direct children - the versions and destinations folders + TreeNode versionNode = new TreeNode(MSG.view_bundle_versions()); + versionNode.setID(bundleGroup.getId() + "_" + bundle.getId() + "_versions"); + versionNode.setParentID(bundleGroup.getId() + "_" + bundle.getId()); + versionNode.setName(MSG.view_bundle_versions()); + records.add(versionNode); + + TreeNode deploymentsNode = new TreeNode(MSG.view_bundle_destinations()); + deploymentsNode.setID(bundleGroup.getId() + "_" + bundle.getId() + "_destinations"); + deploymentsNode.setParentID(bundleGroup.getId() + "_" + bundle.getId()); + deploymentsNode.setName(MSG.view_bundle_destinations()); + records.add(deploymentsNode); + } + } + + } else if (item instanceof Bundle) { Bundle bundle = (Bundle) item;
// each bundle has two direct children - the versions and destinations folders TreeNode versionNode = new TreeNode(MSG.view_bundle_versions()); - versionNode.setID(bundle.getId() + "_versions"); - versionNode.setParentID(String.valueOf(bundle.getId())); + versionNode.setID(bundleGroupId.toString() + "_" + bundle.getId() + "_versions"); + versionNode.setParentID(bundleGroupId.toString() + "_" + bundle.getId()); versionNode.setName(MSG.view_bundle_versions()); - versionNode.setAttribute("name", MSG.view_bundle_versions()); records.add(versionNode);
TreeNode deploymentsNode = new TreeNode(MSG.view_bundle_destinations()); - deploymentsNode.setID(bundle.getId() + "_destinations"); - deploymentsNode.setParentID(String.valueOf(bundle.getId())); + deploymentsNode.setID(bundleGroupId.toString() + "_" + bundle.getId() + "_destinations"); + deploymentsNode.setParentID(bundleGroupId.toString() + "_" + bundle.getId()); deploymentsNode.setName(MSG.view_bundle_destinations()); records.add(deploymentsNode); + } else if (item instanceof BundleDestination) { - if (canManageBundles) { - BundleDestination dest = (BundleDestination) item; + BundleDestination dest = (BundleDestination) item;
- // each destination has 0, 1 or more deployments - if (dest.getDeployments() != null) { - for (BundleDeployment deploy : dest.getDeployments()) { - records.add(copyValuesForKnownBundle(deploy, bundleId)); - } + // each destination has 0, 1 or more deployments + if (dest.getDeployments() != null) { + for (BundleDeployment deploy : dest.getDeployments()) { + records.add(copyValuesForKnownBundle(deploy, bundleGroupId, bundleId)); } } } @@ -233,24 +308,32 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> {
@Override public ListGridRecord copyValues(Object from) { - return copyValuesForKnownBundle(from, null); + return copyValuesForKnownBundle(from, null, null); }
- public ListGridRecord copyValuesForKnownBundle(Object from, Integer bundleId) { + private ListGridRecord copyValuesForKnownBundle(Object from, Integer bundleGroupId, Integer bundleId) { String parentID; TreeNode node = new TreeNode(); - if (from instanceof Bundle) { + if (from instanceof BundleGroup) { + BundleGroup bundleGroup = (BundleGroup) from; + node.setIsFolder(true); + node.setIcon("subsystems/bundle/BundleGroup_16.png"); + node.setID(String.valueOf(bundleGroup.getId())); + node.setName(StringUtility.escapeHtml(bundleGroup.getName())); + + } else if (from instanceof Bundle) { Bundle bundle = (Bundle) from; node.setIsFolder(true); node.setIcon("subsystems/bundle/Bundle_16.png"); - node.setID(String.valueOf(bundle.getId())); + node.setID(String.valueOf(bundleGroupId) + "_" + bundle.getId()); + node.setParentID(String.valueOf(bundleGroupId)); node.setName(StringUtility.escapeHtml(bundle.getName()));
} else if (from instanceof BundleVersion) { BundleVersion version = (BundleVersion) from; node.setIsFolder(false); node.setIcon("subsystems/bundle/BundleVersion_16.png"); - parentID = version.getBundle().getId() + "_versions"; + parentID = bundleGroupId.toString() + "_" + version.getBundle().getId() + "_versions"; node.setParentID(parentID); node.setID(parentID + '_' + version.getId()); node.setName(version.getVersion()); @@ -259,7 +342,7 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { BundleDeployment deployment = (BundleDeployment) from; node.setIsFolder(false); node.setIcon("subsystems/bundle/BundleDeployment_16.png"); - parentID = bundleId + "_destinations_" + deployment.getDestination().getId(); + parentID = bundleGroupId.toString() + "_" + bundleId + "_destinations_" + deployment.getDestination().getId(); node.setParentID(parentID); node.setID(bundleId + "_deployments_" + deployment.getId()); String name = StringUtility.escapeHtml(deployment.getName()); @@ -273,7 +356,7 @@ public class BundleTreeDataSource extends RPCDataSource<Object, Criteria> { BundleDestination destination = (BundleDestination) from; node.setIsFolder(true); node.setIcon("subsystems/bundle/BundleDestination_16.png"); - parentID = destination.getBundle().getId() + "_destinations"; + parentID = bundleGroupId.toString() + "_" + destination.getBundle().getId() + "_destinations"; node.setParentID(parentID); node.setID(parentID + '_' + destination.getId()); node.setName(StringUtility.escapeHtml(destination.getName())); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java index 242f0ef..df01fda 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/tree/BundleTreeView.java @@ -39,6 +39,7 @@ import org.rhq.enterprise.gui.coregui.client.ViewPath;
/** * @author Greg Hinkle + * @author John Mazzitelli */ public class BundleTreeView extends TreeGrid {
@@ -46,12 +47,14 @@ public class BundleTreeView extends TreeGrid { // If so, hold it here and retry after the datasource pulls the data. private ViewPath pendingPath = null;
- public BundleTreeView(boolean canManageBundles) { + private Integer currentlySelectedBundleGroupId; + + public BundleTreeView() { super(); setWidth100(); setHeight100(); setLeaveScrollbarGap(false); - // fetch the top bundle nodes at the inital onDraw() + // fetch the top bundle group nodes at the inital onDraw() setAutoFetchData(true); setAnimateFolders(false); setSelectionType(SelectionStyle.SINGLE); @@ -59,13 +62,27 @@ public class BundleTreeView extends TreeGrid { setSortField("name"); setShowHeader(false);
- setDataSource(new BundleTreeDataSource(canManageBundles)); + setDataSource(new BundleTreeDataSource());
addNodeClickHandler(new NodeClickHandler() { public void onNodeClick(NodeClickEvent event) { TreeNode node = event.getNode(); String path = node.getAttribute("id").replaceAll("_", "/"); - CoreGUI.goToView("Bundles/Bundle/" + path); + + // the node ID is the path the form <bundleGroupId>_<the rest of the node ID> + String[] splitPath = path.split("/", 2); + + try { + currentlySelectedBundleGroupId = Integer.parseInt(splitPath[0]); + } catch (NumberFormatException e) { + CoreGUI.getErrorHandler().handleError("Cannot determine the selected bundle group: " + path); + } + + if (splitPath.length == 1) { + CoreGUI.goToView("Bundles"); + } else { + CoreGUI.goToView("Bundles/Bundle/" + splitPath[1]); + } } }); }
commit 3139a88b6b28ea38de2dbeaf5454003bdad1c2dd Author: Jay Shaughnessy jshaughn@redhat.com Date: Wed Aug 14 11:00:37 2013 -0400
add initial bundle groups (tab) support to the bundle detail view
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java index 57330f9..f1400ee 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java @@ -118,6 +118,7 @@ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGro //criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
criteria.addFilterName(getFilter(request, "search", String.class)); + criteria.addFilterBundleIds(getArrayFilter(request, "bundleIds", Integer.class)); criteria.fetchBundles(true);
return criteria; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java index 9087718..8fb2c08 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java @@ -19,6 +19,7 @@ package org.rhq.enterprise.gui.coregui.client.bundle.group;
import java.util.ArrayList; +import java.util.HashSet; import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback; @@ -64,7 +65,7 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i /** * Creates a new list view. * - * @param globalPermissions if perms is null, no button actions will be shown in the table + * @param globalPermissions if null, no buttons will be active, otherwise normal authz in place */ public BundleGroupsListView(Set<Permission> globalPermissions) { this(null, globalPermissions); @@ -72,7 +73,7 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i
public BundleGroupsListView(Criteria criteria, Set<Permission> globalpermissions) { super(MSG.common_title_bundleGroups(), criteria); - this.globalPermissions = globalpermissions; + this.globalPermissions = (null != globalpermissions) ? globalpermissions : new HashSet<Permission>(); setHeaderIcon(IconEnum.BUNDLE_GROUP.getIcon24x24Path()); setDataSource(new BundleGroupsDataSource()); } @@ -115,9 +116,9 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i } });
- boolean hasAuth = globalPermissions.contains(Permission.MANAGE_BUNDLE_GROUPS); + boolean hasAuthz = globalPermissions.contains(Permission.MANAGE_BUNDLE_GROUPS);
- addTableAction(MSG.common_button_new(), null, new AbstractTableAction((hasAuth) ? TableActionEnablement.ALWAYS + addTableAction(MSG.common_button_new(), null, new AbstractTableAction((hasAuthz) ? TableActionEnablement.ALWAYS : TableActionEnablement.NEVER) { public void executeAction(ListGridRecord[] selection, Object actionValue) { newDetails(); @@ -125,7 +126,7 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i });
addTableAction(MSG.common_button_delete(), MSG.view_bundleGroup_deleteConfirm(), new AbstractTableAction( - (hasAuth) ? TableActionEnablement.ANY : TableActionEnablement.NEVER) { + (hasAuthz) ? TableActionEnablement.ANY : TableActionEnablement.NEVER) { public void executeAction(ListGridRecord[] selections, Object actionValue) { if (selections == null || selections.length == 0) { return; diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java index a3bc0d8..60ec76d 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java @@ -52,6 +52,7 @@ import org.rhq.enterprise.gui.coregui.client.bundle.deploy.BundleDeployWizard; import org.rhq.enterprise.gui.coregui.client.bundle.deployment.BundleDeploymentView; import org.rhq.enterprise.gui.coregui.client.bundle.destination.BundleDestinationListView; import org.rhq.enterprise.gui.coregui.client.bundle.destination.BundleDestinationView; +import org.rhq.enterprise.gui.coregui.client.bundle.group.BundleGroupsListView; import org.rhq.enterprise.gui.coregui.client.bundle.version.BundleVersionListView; import org.rhq.enterprise.gui.coregui.client.bundle.version.BundleVersionView; import org.rhq.enterprise.gui.coregui.client.components.HeaderLabel; @@ -75,6 +76,7 @@ public class BundleView extends EnhancedVLayout implements BookmarkableView { private TabSet tabs; private Tab versionsTab; private Tab destinationsTab; + private Tab bundleGroupsTab;
private BundleGWTServiceAsync bundleManager = GWTServiceLookup.getBundleService(); private Bundle bundle; @@ -100,8 +102,10 @@ public class BundleView extends EnhancedVLayout implements BookmarkableView { tabs = new TabSet(); versionsTab = createVersionsTab(); destinationsTab = createDestinationsTab(); + bundleGroupsTab = createBundleGroupsTab(); tabs.addTab(versionsTab); tabs.addTab(destinationsTab); + tabs.addTab(bundleGroupsTab);
addMember(backButton); addMember(headerLabel); @@ -161,6 +165,14 @@ public class BundleView extends EnhancedVLayout implements BookmarkableView { return versionsTab; }
+ private Tab createBundleGroupsTab() { + Tab bundleGroupsTab = new Tab(MSG.common_title_bundleGroups()); + Criteria criteria = new Criteria(); + criteria.addCriteria("bundleIds", new Integer[] { bundle.getId() }); + bundleGroupsTab.setPane(new BundleGroupsListView(criteria, (Set<Permission>) null)); + return bundleGroupsTab; + } + private DynamicForm createSummaryForm() {
form = new DynamicForm();
commit 318704c05f4f6d5750157ce62d7d69b7c8af5b1d Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 13 17:25:05 2013 -0400
make sure to fetch bundles for the fetched bundle groups, so that the selector reflects the current membership
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java index 8b85078..57330f9 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java @@ -118,6 +118,7 @@ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGro //criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class));
criteria.addFilterName(getFilter(request, "search", String.class)); + criteria.fetchBundles(true);
return criteria; }
commit 99767cc9438e45b0abbdc82702cf13b07c476de7 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 13 16:27:08 2013 -0400
Fix name link issue and a few other things
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java index 48c0fe2..e3937c0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java @@ -56,19 +56,24 @@ public class BundleSectionView extends SectionStack implements RefreshableView { setVisibilityMode(VisibilityMode.MULTIPLE); setWidth100(); setHeight100(); + + init(); }
- public void onDraw() { + public void init() { bundlesSection = new SectionStackSection(MSG.common_title_bundles()); - bundlesSection.setExpanded(true); bundlesListView = new BundlesListView(globalPermissions); bundlesSection.addItem(bundlesListView); + bundlesSection.setExpanded(true); this.addSection(bundlesSection);
bundleGroupsSection = new SectionStackSection(MSG.common_title_bundleGroups()); bundleGroupsListView = new BundleGroupsListView(globalPermissions); bundleGroupsSection.addItem(bundleGroupsListView); + bundleGroupsSection.setExpanded(true); this.addSection(bundleGroupsSection); + + setExpansion(true, true); }
@Override @@ -78,12 +83,10 @@ public class BundleSectionView extends SectionStack implements RefreshableView { markForRedraw(); }
- public void setBundlesExpanded(boolean expanded) { - bundlesSection.setExpanded(expanded); - } - - public void setBundleGroupsExpanded(boolean expanded) { - bundleGroupsSection.setExpanded(expanded); + public void setExpansion(boolean bundlesExpanded, boolean bundleGroupsExpanded) { + bundlesSection.setExpanded(bundlesExpanded); + bundleGroupsSection.setExpanded(bundleGroupsExpanded); + markForRedraw(); }
} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java index 411cef4..4cf3f0f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java @@ -105,9 +105,12 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView { bundleSectionView.refresh(); } else { bundleSectionView = new BundleSectionView(globalPermissions); - if (viewPath.isNextEnd() && viewPath.getNext().getPath().equals("BundleGroup")) { - bundleSectionView.setBundlesExpanded(false); - bundleSectionView.setBundleGroupsExpanded(true); + if (!viewPath.isEnd()) { + if (viewPath.getCurrent().getPath().equals("BundleGroup")) { + bundleSectionView.setExpansion(false, true); + } else { + bundleSectionView.setExpansion(true, false); + } } setContent(bundleSectionView); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java index 1c91e07..9087718 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java @@ -37,7 +37,6 @@ import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.enterprise.gui.coregui.client.CoreGUI; import org.rhq.enterprise.gui.coregui.client.IconEnum; import org.rhq.enterprise.gui.coregui.client.LinkManager; -import org.rhq.enterprise.gui.coregui.client.bundle.list.BundlesWithLatestVersionDataSource; import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction; import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement; import org.rhq.enterprise.gui.coregui.client.components.table.TableSection; @@ -88,7 +87,7 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i nameField.setWidth("33%"); nameField.setCellFormatter(new CellFormatter() { public String format(Object value, ListGridRecord record, int i, int i1) { - return "<a href="" + record.getAttribute(BundlesWithLatestVersionDataSource.FIELD_NAMELINK) + "">" + return "<a href="" + record.getAttribute(BundleGroupsDataSource.FIELD_NAMELINK) + "">" + StringUtility.escapeHtml(String.valueOf(value)) + "</a>"; } }); @@ -147,13 +146,13 @@ public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> i public void onFailure(Throwable caught) { String names = doomedNames.toString(); String error = ErrorHandler.getAllMessages(caught); - Message m = new Message(MSG.view_bundle_list_deletesFailure(), names + "<br/>\n" + error, + Message m = new Message(MSG.view_bundleGroup_deletesFailure(), names + "<br/>\n" + error, Severity.Error); CoreGUI.getMessageCenter().notify(m); }
public void onSuccess(Void result) { - Message m = new Message(MSG.view_bundle_list_deletesSuccessful(), doomedNames.toString(), + Message m = new Message(MSG.view_bundleGroup_deletesSuccessful(), doomedNames.toString(), Severity.Info); CoreGUI.getMessageCenter().notify(m); CoreGUI.refresh(); 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 21fc3bb..6f6e30e 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 @@ -1182,6 +1182,8 @@ view_autoDiscoveryQ_unignoreInProgress = Unignoring the selected Resources... view_autoDiscoveryQ_unignoreSuccessful = You have successfully unignored the selected Resources. view_autoDiscoveryQ_uninventoried = Uninventoried view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +view_bundleGroup_deletesFailure = Failed to delete the bundle groups +view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups view_bundleVersion_loadFailure = Failed to load bundle version data view_bundle_bundleDeployment = Bundle Deployment view_bundle_bundleDeployments = Bundle Deployments diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index 4826b90..72c70a3 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -1196,6 +1196,8 @@ view_autoDiscoveryQ_unignoreInProgress = Odignorování vybraných zdrojů práv view_autoDiscoveryQ_unignoreSuccessful = Vybrané zdroje byly úspěšně odignorovány. view_autoDiscoveryQ_uninventoried = Odinventarizovaný ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups view_bundleVersion_loadFailure = Nepodařilo se načíst data verzí balíků view_bundle_bundleDeployment = Nasazení balíku view_bundle_bundleDeployments = Nasazování balíků diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index 2a67608..099c61e 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -1100,6 +1100,8 @@ view_autoDiscoveryQ_unignoreFailure = Konnte das Ignorieren für die Ressourcen view_autoDiscoveryQ_unignoreSuccessful = Sie haben erfolgreich das Ignorieren der ausgewählten Ressourcen aufgehoben. view_autoDiscoveryQ_uninventoried = Aus dem Inventory gelöscht ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups ##view_bundleVersion_loadFailure = Failed to load bundle version data ##view_bundle_bundleDeployment = Bundle Deployment ##view_bundle_bundleDeployments = Bundle Deployments @@ -1226,6 +1228,8 @@ view_bundle_list_backToAll = Zurück zur Bundle-Übersicht view_bundle_list_deleteConfirm = Sind Sie sicher, dass Sie dieses Bundle löschen wollen? view_bundle_list_deleteFailure = Löschen des Bundles [{0}] fehlgeschlagen ##view_bundle_list_deleteSuccessful = You successfully deleted the bundle named [{0}] +##view_bundle_list_deletesFailure = Failed to delete the bundles +##view_bundle_list_deletesSuccessful = You successfully deleted the bundles view_bundle_list_destinationsCount = Anzahl Ziele ##view_bundle_list_error1 = Failed to load bundle to deploy [{0}] ##view_bundle_list_error2 = Failed to get a single bundle to deploy [{0}] diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index 5f53171..64f8f3d 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -1172,6 +1172,8 @@ view_autoDiscoveryQ_unignoreInProgress = 選択されたリソースの無視を view_autoDiscoveryQ_unignoreSuccessful = 選択したリソースの無視解除に成功しました view_autoDiscoveryQ_uninventoried = インベントリ登録をしない ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups view_bundleVersion_loadFailure = バンドルバージョンデータをロードするのに失敗しました view_bundle_bundleDeployment = バンドルデプロイメント view_bundle_bundleDeployments = バンドルデプロイメント diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index e41b243..c23a937 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -1055,6 +1055,8 @@ view_autoDiscoveryQ_unignoreInProgress = 선택된 리소스를 무시 안하는 view_autoDiscoveryQ_unignoreSuccessful = 선택된 리소스를 무시 안하는데 성공했습니다. view_autoDiscoveryQ_uninventoried = 인벤토리 해제 ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups view_bundleVersion_loadFailure = 번들 버전 데이터를 로드하는데 실패했습니다. view_bundle_bundleDeployment = 번들 배포 view_bundle_bundleDeployments = 번들 배포 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index d5c7243..37b3277 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -1184,6 +1184,8 @@ view_autoDiscoveryQ_unignoreInProgress = Removendo status de recurso ignorado... view_autoDiscoveryQ_unignoreSuccessful = Status de recurso ignorado removido com sucesso para os recursos selecionados. view_autoDiscoveryQ_uninventoried = Removido do invent\u00E1rio ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups view_bundleVersion_loadFailure = Falha ao carregar dados da vers\u00E3o do bundle view_bundle_bundleDeployment = Implanta\u00E7\u00E3o do Bundle view_bundle_bundleDeployments = Implanta\u00E7\u00F5es do Bundle diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index d88a392..6b44762 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2755,7 +2755,11 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль ##view_autoDiscoveryQ_field_inventoryStatus = Inventory Status ##view_autoDiscoveryQ_ignore = Ignore ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups ##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. +##view_bundle_list_deletesFailure = Failed to delete the bundles +##view_bundle_list_deletesSuccessful = You successfully deleted the bundles ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1} ##view_configEdit_description = Description ##view_configEdit_property = Vlastnost diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index 14d4f90..eb163d6 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -1169,6 +1169,8 @@ view_autoDiscoveryQ_unignoreInProgress = Unignoring the selected Resources... view_autoDiscoveryQ_unignoreSuccessful = \u6210\u529f\u4f7f\u9009\u4e2d\u7684\u8d44\u6e90\u751f\u6548. view_autoDiscoveryQ_uninventoried = Uninventoried ##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundleGroup_deletesFailure = Failed to delete the bundle groups +##view_bundleGroup_deletesSuccessful = You successfully deleted the bundle groups view_bundleVersion_loadFailure = \u52a0\u8f7dbundle\u7248\u672c\u6570\u636e\u5931\u8d25 view_bundle_bundleDeployment = Bundle\u53d1\u5e03 view_bundle_bundleDeployments = Bundle\u53d1\u5e03
commit a3de29602a8e3303b05897e797cedb686130c9b9 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 13 15:03:27 2013 -0400
First pass at adding in bundle group view/create/delete support, work in progress.
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java index b48a712..0aa613f 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/IconEnum.java @@ -80,6 +80,7 @@ public enum IconEnum { // Bundle Tab ///////////////////////////// BUNDLE("subsystems/bundle/Bundle_16.png", "subsystems/bundle/Bundle_24.png"), + BUNDLE_GROUP("subsystems/bundle/BundleGroup_16.png", "subsystems/bundle/BundleGroup_24.png"), BUNDLE_DELETE("subsystems/bundle/BundleAction_Delete_16.png", "subsystems/bundle/BundleAction_Delete_24.png"), BUNDLE_DEPLOY("subsystems/bundle/BundleAction_Deploy_16.png", "subsystems/bundle/BundleAction_Deploy_24.png"), BUNDLE_DESTINATION("subsystems/bundle/BundleDestination_16.png", "subsystems/bundle/BundleDestination_24.png"), diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java index 5513872..dd7aaa3 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/LinkManager.java @@ -505,6 +505,10 @@ public class LinkManager { return "#Bundles/Bundle/" + bundleId; }
+ public static String getBundleGroupLink(int bundleGroupId) { + return "#Bundles/BundleGroup/" + bundleGroupId; + } + public static String getBundleVersionLink(int bundleId, int bundleVersionId) { return "#Bundles/Bundle/" + bundleId + "/versions" + (bundleVersionId == 0 ? "" : ("/" + bundleVersionId)); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java new file mode 100644 index 0000000..48c0fe2 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSectionView.java @@ -0,0 +1,89 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.bundle; +import java.util.Set; + +import com.smartgwt.client.types.VisibilityMode; +import com.smartgwt.client.widgets.layout.SectionStack; +import com.smartgwt.client.widgets.layout.SectionStackSection; + +import org.rhq.core.domain.authz.Permission; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.Messages; +import org.rhq.enterprise.gui.coregui.client.RefreshableView; +import org.rhq.enterprise.gui.coregui.client.bundle.group.BundleGroupsListView; +import org.rhq.enterprise.gui.coregui.client.bundle.list.BundlesListView; + + +/** + * This is a section stack view for the bundle main view (the right hand side) showing a bundles list view section + * and a bundle groups list view section. + * + * @author Jay Shaughnessy + */ +public class BundleSectionView extends SectionStack implements RefreshableView { + + final static Messages MSG = CoreGUI.getMessages(); + + private SectionStackSection bundlesSection; + private SectionStackSection bundleGroupsSection; + private BundlesListView bundlesListView; + private BundleGroupsListView bundleGroupsListView; + + private Set<Permission> globalPermissions; + + public BundleSectionView(Set<Permission> globalPermissions) { + super(); + + this.globalPermissions = globalPermissions; + + setVisibilityMode(VisibilityMode.MULTIPLE); + setWidth100(); + setHeight100(); + } + + public void onDraw() { + bundlesSection = new SectionStackSection(MSG.common_title_bundles()); + bundlesSection.setExpanded(true); + bundlesListView = new BundlesListView(globalPermissions); + bundlesSection.addItem(bundlesListView); + this.addSection(bundlesSection); + + bundleGroupsSection = new SectionStackSection(MSG.common_title_bundleGroups()); + bundleGroupsListView = new BundleGroupsListView(globalPermissions); + bundleGroupsSection.addItem(bundleGroupsListView); + this.addSection(bundleGroupsSection); + } + + @Override + public void refresh() { + bundlesListView.refresh(); + bundleGroupsListView.refresh(); + markForRedraw(); + } + + public void setBundlesExpanded(boolean expanded) { + bundlesSection.setExpanded(expanded); + } + + public void setBundleGroupsExpanded(boolean expanded) { + bundleGroupsSection.setExpanded(expanded); + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java index f3f0328..034d3e0 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleSelector.java @@ -27,6 +27,7 @@ import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.SelectItem; import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.grid.ListGridRecord;
import org.rhq.core.domain.bundle.Bundle; import org.rhq.core.domain.bundle.BundleType; @@ -50,6 +51,11 @@ public class BundleSelector extends AbstractSelector<Bundle, BundleCriteria> { super(); }
+ public BundleSelector(ListGridRecord[] initiallyAssigned, boolean isReadOnly) { + super(isReadOnly); + setAssigned(initiallyAssigned); + } + protected DynamicForm getAvailableFilterForm() { DynamicForm availableFilterForm = new DynamicForm(); availableFilterForm.setNumCols(4); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java index d3f4e8c..411cef4 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/BundleTopView.java @@ -34,15 +34,13 @@ import org.rhq.enterprise.gui.coregui.client.PermissionsLoadedListener; import org.rhq.enterprise.gui.coregui.client.PermissionsLoader; import org.rhq.enterprise.gui.coregui.client.ViewId; import org.rhq.enterprise.gui.coregui.client.ViewPath; +import org.rhq.enterprise.gui.coregui.client.bundle.group.BundleGroupEditView; import org.rhq.enterprise.gui.coregui.client.bundle.list.BundleView; -import org.rhq.enterprise.gui.coregui.client.bundle.list.BundlesListView; import org.rhq.enterprise.gui.coregui.client.bundle.tree.BundleTreeView; import org.rhq.enterprise.gui.coregui.client.components.view.ViewName; -import org.rhq.enterprise.gui.coregui.client.content.repository.tree.ContentRepositoryTreeView; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedHLayout; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedUtility;
- /** * This is the main bundle view with left hand side trees and right hand side list/details view. * @@ -51,14 +49,15 @@ import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedUtility; */ public class BundleTopView extends EnhancedHLayout implements BookmarkableView {
- public static final ViewName VIEW_ID = new ViewName("Bundles", MSG.view_bundle_bundles(), IconEnum.BUNDLE); - - private ViewId currentNextPath; + public static final ViewName VIEW_ID = new ViewName("Bundles", MSG.common_title_bundles(), IconEnum.BUNDLE);
private BundleTreeView bundleTreeView; // the tree of bundle destinations and versions private VLayout contentCanvas; // the right-side canvas container - private BundleView bundleView; // if the user is viewing an individual bundle, this is that right-side view - private BundlesListView bundlesListView; // if the user is not viewing an indiv. bundle, this is the right-side list + private BundleSectionView bundleSectionView; // if the user is not viewing bundle or bundle group detail, this is the RHS view + private BundleView bundleView; // if the user is viewing bundle detail, this is the RHS view + private BundleGroupEditView bundleGroupView; // if the user is viewing bundle group detail, this is the RHS view + private ViewId currentBundleViewId; + private ViewId currentBundleGroupViewId;
public BundleTopView() { super(); @@ -70,12 +69,9 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView { public void renderView(final ViewPath viewPath) { new PermissionsLoader().loadExplicitGlobalPermissions(new PermissionsLoadedListener() { @Override - public void onPermissionsLoaded(Set<Permission> permissions) { + public void onPermissionsLoaded(Set<Permission> globalPermissions) { // if we haven't done it yet, build the view components if (bundleTreeView == null) { - boolean canManageInventory = permissions != null - && permissions.contains(Permission.MANAGE_INVENTORY); - boolean canManageBundles = permissions != null && permissions.contains(Permission.MANAGE_BUNDLE);
SectionStack sectionStack = new SectionStack(); sectionStack.setShowResizeBar(true); @@ -83,24 +79,12 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView { sectionStack.setWidth(250); sectionStack.setHeight100();
- SectionStackSection bundlesSection = new SectionStackSection(MSG.view_bundle_bundles()); - bundleTreeView = new BundleTreeView(canManageBundles); + SectionStackSection bundlesSection = new SectionStackSection(MSG.common_title_bundles()); + // TODO: Need to fix perm stuff in tree view + bundleTreeView = new BundleTreeView(true); bundlesSection.addItem(bundleTreeView); sectionStack.addSection(bundlesSection);
- // we only show repositories if the user has the global manage_inventory perms since that is required - if (canManageInventory) { - SectionStackSection repositoriesSection = new SectionStackSection(MSG - .common_title_repositories()); - ContentRepositoryTreeView repoTree = new ContentRepositoryTreeView(); - repositoriesSection.addItem(repoTree); - sectionStack.addSection(repositoriesSection); - } - - // TODO: we aren't doing anything with providers yet - // SectionStackSection providersSection = new SectionStackSection(MSG.common_title_providers()); - // sectionStack.addSection(providersSection); - addMember(sectionStack);
contentCanvas = new VLayout(); @@ -115,22 +99,42 @@ public class BundleTopView extends EnhancedHLayout implements BookmarkableView {
bundleTreeView.selectPath(viewPath);
- if (viewPath.isEnd()) { - if (currentNextPath == null && bundlesListView != null) { - bundlesListView.refresh(); + if (viewPath.isEnd() || viewPath.isNextEnd()) { + // We are navigating to the section view (ignore any trailing segment without an ID) + if (currentBundleViewId == null && currentBundleGroupViewId == null && bundleSectionView != null) { + bundleSectionView.refresh(); } else { - currentNextPath = null; - bundlesListView = new BundlesListView(permissions); - setContent(bundlesListView); + bundleSectionView = new BundleSectionView(globalPermissions); + if (viewPath.isNextEnd() && viewPath.getNext().getPath().equals("BundleGroup")) { + bundleSectionView.setBundlesExpanded(false); + bundleSectionView.setBundleGroupsExpanded(true); + } + setContent(bundleSectionView); } } else { - if (!viewPath.getNext().equals(currentNextPath)) { - currentNextPath = viewPath.getNext(); - bundleView = new BundleView(permissions); - setContent(bundleView); - bundleView.renderView(viewPath.next()); - } else { - bundleView.renderView(viewPath.next()); + // we are navigating to bundle detail or bundle group detail + String currentPath = viewPath.getCurrent().getPath(); + ViewPath nextViewPath = viewPath.next(); // the ID segment + + if ("Bundle".equals(currentPath)) { + if (!nextViewPath.equals(currentBundleViewId)) { + // set new bundle detail + currentBundleViewId = nextViewPath.getCurrent(); + bundleView = new BundleView(globalPermissions); + setContent(bundleView); + } + bundleView.renderView(nextViewPath); + + } else if ("BundleGroup".equals(currentPath)) { + if (!nextViewPath.equals(currentBundleGroupViewId)) { + // set new bundle detail + currentBundleGroupViewId = nextViewPath.getCurrent(); + bundleGroupView = new BundleGroupEditView(globalPermissions, Integer + .parseInt(currentBundleGroupViewId.getPath())); + setContent(bundleGroupView); + } + // redisplay the current bundle group detail + bundleGroupView.renderView(nextViewPath); } } } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentView.java index d888d00..afc94e4 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentView.java @@ -79,9 +79,9 @@ import org.rhq.enterprise.gui.coregui.client.components.tagging.TagsChangedCallb import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; +import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/** * @author Greg Hinkle @@ -148,7 +148,7 @@ public class BundleDeploymentView extends EnhancedVLayout implements Bookmarkabl form.setPadding(5);
StaticTextItem bundleName = new StaticTextItem("bundle"); - bundleName.setTitle(MSG.view_bundle_bundle()); + bundleName.setTitle(MSG.common_title_bundle()); bundleName.setValue("<a href="" + LinkManager.getBundleLink(bundle.getId()) + "">" + StringUtility.escapeHtml(bundle.getName()) + "</a>");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationDataSource.java index 28d64b6..05a9611 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationDataSource.java @@ -83,7 +83,7 @@ public class BundleDestinationDataSource extends RPCDataSource<BundleDestination DataSourceTextField description = new DataSourceTextField(FIELD_DESCRIPTION, MSG.common_title_description()); fields.add(description);
- DataSourceTextField bundle = new DataSourceTextField(FIELD_BUNDLE_NAME, MSG.view_bundle_bundle()); + DataSourceTextField bundle = new DataSourceTextField(FIELD_BUNDLE_NAME, MSG.common_title_bundle()); fields.add(bundle);
DataSourceTextField group = new DataSourceTextField(FIELD_GROUP_NAME, MSG.view_bundle_dest_group()); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java index 00922a8..1adbc68 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationListView.java @@ -62,7 +62,7 @@ public class BundleDestinationListView extends Table<BundleDestinationDataSource ListGridField descriptionField = new ListGridField(BundleDestinationDataSource.FIELD_DESCRIPTION, MSG.common_title_description()); ListGridField bundleNameField = new ListGridField(BundleDestinationDataSource.FIELD_BUNDLE_NAME, - MSG.view_bundle_bundle()); + MSG.common_title_bundle()); ListGridField groupNameField = new ListGridField(BundleDestinationDataSource.FIELD_GROUP_NAME, MSG.view_bundle_dest_group()); ListGridField baseDirNameField = new ListGridField(BundleDestinationDataSource.FIELD_BASE_DIR_NAME, diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationView.java index 4e08485..8f6b8ac 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationView.java @@ -61,9 +61,9 @@ import org.rhq.enterprise.gui.coregui.client.components.tagging.TagsChangedCallb import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; +import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/** * @author Greg Hinkle @@ -127,7 +127,7 @@ public class BundleDestinationView extends EnhancedVLayout implements Bookmarkab form.setPadding(5);
StaticTextItem bundleName = new StaticTextItem("bundle"); - bundleName.setTitle(MSG.view_bundle_bundle()); + bundleName.setTitle(MSG.common_title_bundle()); bundleName.setValue("<a href="" + LinkManager.getBundleLink(bundle.getId()) + "">" + StringUtility.escapeHtml(bundle.getName()) + "</a>");
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupEditView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupEditView.java new file mode 100644 index 0000000..c8473a3 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupEditView.java @@ -0,0 +1,182 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.bundle.group; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import com.smartgwt.client.data.DSRequest; +import com.smartgwt.client.data.Record; +import com.smartgwt.client.types.Overflow; +import com.smartgwt.client.widgets.Canvas; +import com.smartgwt.client.widgets.form.fields.FormItem; +import com.smartgwt.client.widgets.form.fields.TextItem; +import com.smartgwt.client.widgets.grid.ListGridRecord; +import com.smartgwt.client.widgets.tab.Tab; +import com.smartgwt.client.widgets.tab.TabSet; + +import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.bundle.BundleGroup; +import org.rhq.enterprise.gui.coregui.client.IconEnum; +import org.rhq.enterprise.gui.coregui.client.ImageManager; +import org.rhq.enterprise.gui.coregui.client.ViewPath; +import org.rhq.enterprise.gui.coregui.client.bundle.BundleSelector; +import org.rhq.enterprise.gui.coregui.client.components.form.AbstractRecordEditor; +import org.rhq.enterprise.gui.coregui.client.components.form.EnhancedDynamicForm; +import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedEvent; +import org.rhq.enterprise.gui.coregui.client.components.selector.AssignedItemsChangedHandler; +import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; + +/** + * @author Jay Shaughnessy + */ +public class BundleGroupEditView extends AbstractRecordEditor<BundleGroupsDataSource> { + + private static final String HEADER_ICON = IconEnum.BUNDLE_GROUP.getIcon24x24Path(); + + private Tab bundlesTab; + private BundleSelector bundleSelector; + private Set<Permission> globalPermissions; + + public BundleGroupEditView(Set<Permission> globalPermissions, int bundleGroupId) { + super(new BundleGroupsDataSource(), bundleGroupId, MSG.common_title_bundleGroups(), HEADER_ICON); + + this.globalPermissions = globalPermissions; + } + + @Override + public void renderView(ViewPath viewPath) { + super.renderView(viewPath); + + init(!globalPermissions.contains(Permission.MANAGE_BUNDLE_GROUPS)); + } + + @Override + protected EnhancedVLayout buildContentPane() { + EnhancedVLayout contentPane = new EnhancedVLayout(); + contentPane.setWidth100(); + contentPane.setHeight100(); + contentPane.setOverflow(Overflow.AUTO); + + EnhancedDynamicForm form = buildForm(); + setForm(form); + + EnhancedVLayout topPane = new EnhancedVLayout(); + topPane.setWidth100(); + topPane.setHeight(80); + topPane.addMember(form); + + contentPane.addMember(topPane); + + TabSet tabSet = new TabSet(); + tabSet.setWidth100(); + tabSet.setHeight100(); + + this.bundlesTab = buildBundlesTab(tabSet); + tabSet.addTab(bundlesTab); + + contentPane.addMember(tabSet); + + return contentPane; + } + + private Tab buildBundlesTab(TabSet tabSet) { + Tab tab = new Tab(MSG.common_title_bundles(), ImageManager.getBundleIcon()); + // NOTE: We will set the tab content to the bundle selector later, once the Bundle Group has been fetched. + + return tab; + } + + @Override + protected Record createNewRecord() { + BundleGroup bundleGroup = new BundleGroup(); + Record bundleGroupRecord = BundleGroupsDataSource.getInstance().copyValues(bundleGroup); + return bundleGroupRecord; + } + + @Override + protected void editRecord(Record record) { + super.editRecord(record); + + Record[] bundleRecords = record.getAttributeAsRecordArray(BundleGroupsDataSource.FIELD_BUNDLES); + ListGridRecord[] bundleListGridRecords = toListGridRecordArray(bundleRecords); + + this.bundleSelector = new BundleSelector(bundleListGridRecords, + !globalPermissions.contains(Permission.MANAGE_BUNDLE_GROUPS)); + this.bundleSelector.addAssignedItemsChangedHandler(new AssignedItemsChangedHandler() { + public void onSelectionChanged(AssignedItemsChangedEvent event) { + BundleGroupEditView.this.onItemChanged(); + } + }); + updateTab(this.bundlesTab, this.bundleSelector); + } + + private static void updateTab(Tab tab, Canvas content) { + if (tab == null) { + throw new IllegalStateException("A null tab was specified."); + } + tab.getTabSet().updateTab(tab, content); + } + + @Override + protected List<FormItem> createFormItems(EnhancedDynamicForm form) { + List<FormItem> items = new ArrayList<FormItem>(); + + TextItem nameItem = new TextItem(BundleGroupsDataSource.FIELD_NAME); + nameItem.setShowTitle(true); + nameItem.setSelectOnFocus(true); + nameItem.setTabIndex(1); + nameItem.setAttribute(EnhancedDynamicForm.OUTPUT_AS_HTML_ATTRIBUTE, true); + items.add(nameItem); + + TextItem descriptionItem = new TextItem(BundleGroupsDataSource.FIELD_DESCRIPTION); + descriptionItem.setShowTitle(true); + descriptionItem.setTabIndex(5); + descriptionItem.setColSpan(form.getNumCols()); + descriptionItem.setAttribute(EnhancedDynamicForm.OUTPUT_AS_HTML_ATTRIBUTE, true); + items.add(descriptionItem); + + return items; + } + + @Override + protected void save(DSRequest requestProperties) { + // Grab the currently assigned bundles from the selector and stick them into the corresponding canvas + // item on the form, so when the form is saved, they'll get submitted along with the rest of the simple fields + // to the datasource's add or update methods. + if (bundleSelector != null) { + ListGridRecord[] bundleRecords = this.bundleSelector.getSelectedRecords(); + getForm().setValue(BundleGroupsDataSource.FIELD_BUNDLES, bundleRecords); + } + + // Submit the form values to the datasource. + super.save(requestProperties); + } + + @Override + protected void reset() { + super.reset(); + + if (this.bundleSelector != null) { + this.bundleSelector.reset(); + } + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java index 4f76f06..8b85078 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsDataSource.java @@ -18,7 +18,10 @@ */ package org.rhq.enterprise.gui.coregui.client.bundle.group;
+import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.DSRequest; @@ -29,10 +32,14 @@ import com.smartgwt.client.data.fields.DataSourceIntegerField; import com.smartgwt.client.data.fields.DataSourceTextField; import com.smartgwt.client.widgets.grid.ListGridRecord;
+import org.rhq.core.domain.bundle.Bundle; import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.core.domain.criteria.BundleGroupCriteria; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.LinkManager; +import org.rhq.enterprise.gui.coregui.client.admin.users.UsersDataSource.Field; +import org.rhq.enterprise.gui.coregui.client.bundle.list.BundlesDataSource; import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; @@ -42,6 +49,12 @@ import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; */ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGroupCriteria> {
+ public static final String FIELD_ID = "id"; + public static final String FIELD_NAME = "name"; + public static final String FIELD_NAMELINK = "nameLink"; + public static final String FIELD_DESCRIPTION = "description"; + public static final String FIELD_BUNDLES = "bundles"; + private BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
private static BundleGroupsDataSource INSTANCE; @@ -63,14 +76,15 @@ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGro protected List<DataSourceField> addDataSourceFields() { List<DataSourceField> fields = super.addDataSourceFields();
- DataSourceIntegerField idField = new DataSourceIntegerField("id", MSG.common_title_id()); + DataSourceIntegerField idField = new DataSourceIntegerField(FIELD_ID, MSG.common_title_id()); idField.setPrimaryKey(true); fields.add(idField);
- DataSourceTextField nameField = new DataSourceTextField("name", MSG.common_title_name()); + DataSourceTextField nameField = new DataSourceTextField(FIELD_NAME, MSG.common_title_name()); fields.add(nameField);
- DataSourceTextField descriptionField = new DataSourceTextField("description", MSG.common_title_description()); + DataSourceTextField descriptionField = new DataSourceTextField(FIELD_DESCRIPTION, + MSG.common_title_description()); fields.add(descriptionField);
return fields; @@ -96,30 +110,94 @@ public class BundleGroupsDataSource extends RPCDataSource<BundleGroup, BundleGro @Override protected BundleGroupCriteria getFetchCriteria(final DSRequest request) { BundleGroupCriteria criteria = new BundleGroupCriteria(); + // may support tags in future, but not in rev1 //criteria.addFilterTagNamespace(getFilter(request, "tagNamespace", String.class)); //criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class)); //criteria.addFilterTagName(getFilter(request, "tagName", String.class)); //criteria.addFilterTagSemantic(getFilter(request, "tagSemantic", String.class)); + criteria.addFilterName(getFilter(request, "search", String.class));
return criteria; }
@Override + protected void executeAdd(final Record recordToAdd, final DSRequest request, final DSResponse response) { + final BundleGroup newBundleGroup = copyValues(recordToAdd); + + bundleService.createBundleGroup(newBundleGroup, new AsyncCallback<BundleGroup>() { + public void onFailure(Throwable caught) { + // TODO: Throw more specific SLSB exceptions so we can set the right validation errors. + String message = caught.getMessage(); + if (message != null && message.contains("javax.persistence.EntityExistsException")) { + Map<String, String> errorMessages = new HashMap<String, String>(); + errorMessages.put(Field.NAME, MSG.view_bundle_fail_existingName(newBundleGroup.getName())); + sendValidationErrorResponse(request, response, errorMessages); + } else { + throw new RuntimeException(caught); + } + } + + public void onSuccess(final BundleGroup createdBundleGroup) { + Record createdBundleGroupRecord = copyValues(createdBundleGroup, false); + sendSuccessResponse(request, response, createdBundleGroupRecord); + } + }); + } + + @Override + protected void executeUpdate(final Record editedBundleGroupRecord, Record oldBundleGroupRecord, + final DSRequest request, final DSResponse response) { + final BundleGroup editedBundleGroup = copyValues(editedBundleGroupRecord); + + bundleService.updateBundleGroup(editedBundleGroup, new AsyncCallback<BundleGroup>() { + public void onFailure(Throwable caught) { + String message = "Failed to update bundle group [" + editedBundleGroup.getName() + "]."; + sendFailureResponse(request, response, message, caught); + } + + public void onSuccess(final BundleGroup updatedBundleGroup) { + sendSuccessResponse(request, response, editedBundleGroupRecord); + } + }); + } + + @Override public BundleGroup copyValues(Record from) { - return (BundleGroup) from.getAttributeAsObject("object"); + BundleGroup to = new BundleGroup(); + + to.setId(from.getAttributeAsInt(FIELD_ID)); + to.setName(from.getAttributeAsString(FIELD_NAME)); + to.setDescription(from.getAttributeAsString(FIELD_DESCRIPTION)); + + Record[] bundleRecords = from.getAttributeAsRecordArray(FIELD_BUNDLES); + Set<Bundle> bundles = new BundlesDataSource().buildDataObjects(bundleRecords); + to.setBundles(bundles); + + return to; }
@Override public ListGridRecord copyValues(BundleGroup from) { + return copyValues(from, true); + } + + @Override + public ListGridRecord copyValues(BundleGroup from, boolean cascade) { ListGridRecord record = new ListGridRecord();
- record.setAttribute("id", from.getId()); - record.setAttribute("name", from.getName()); - record.setAttribute("description", from.getDescription()); + record.setAttribute(FIELD_ID, from.getId()); + record.setAttribute(FIELD_NAME, from.getName()); + record.setAttribute(FIELD_NAMELINK, LinkManager.getBundleGroupLink(from.getId())); + record.setAttribute(FIELD_DESCRIPTION, from.getDescription()); + + if (cascade) { + Set<Bundle> bundles = from.getBundles(); + ListGridRecord[] bundleRecords = new BundlesDataSource().buildRecords(bundles, false); + record.setAttribute(FIELD_BUNDLES, bundleRecords);
- record.setAttribute("object", from); + }
return record; } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java new file mode 100644 index 0000000..1c91e07 --- /dev/null +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/group/BundleGroupsListView.java @@ -0,0 +1,187 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2013 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.coregui.client.bundle.group; + +import java.util.ArrayList; +import java.util.Set; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.smartgwt.client.data.Criteria; +import com.smartgwt.client.types.ListGridFieldType; +import com.smartgwt.client.widgets.Canvas; +import com.smartgwt.client.widgets.events.DoubleClickEvent; +import com.smartgwt.client.widgets.events.DoubleClickHandler; +import com.smartgwt.client.widgets.grid.CellFormatter; +import com.smartgwt.client.widgets.grid.ListGrid; +import com.smartgwt.client.widgets.grid.ListGridField; +import com.smartgwt.client.widgets.grid.ListGridRecord; + +import org.rhq.core.domain.authz.Permission; +import org.rhq.core.domain.bundle.BundleGroup; +import org.rhq.enterprise.gui.coregui.client.CoreGUI; +import org.rhq.enterprise.gui.coregui.client.IconEnum; +import org.rhq.enterprise.gui.coregui.client.LinkManager; +import org.rhq.enterprise.gui.coregui.client.bundle.list.BundlesWithLatestVersionDataSource; +import org.rhq.enterprise.gui.coregui.client.components.table.AbstractTableAction; +import org.rhq.enterprise.gui.coregui.client.components.table.TableActionEnablement; +import org.rhq.enterprise.gui.coregui.client.components.table.TableSection; +import org.rhq.enterprise.gui.coregui.client.components.view.HasViewName; +import org.rhq.enterprise.gui.coregui.client.components.view.ViewName; +import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; +import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; +import org.rhq.enterprise.gui.coregui.client.util.ErrorHandler; +import org.rhq.enterprise.gui.coregui.client.util.StringUtility; +import org.rhq.enterprise.gui.coregui.client.util.message.Message; +import org.rhq.enterprise.gui.coregui.client.util.message.Message.Severity; + +/** + * Shows a list of bundle groups in the system. The list gives you some actions but proper permissions are required. + * + * @author Jay Shaughnessy + */ +public class BundleGroupsListView extends TableSection<BundleGroupsDataSource> implements HasViewName { + + public static final ViewName VIEW_ID = new ViewName("BundleGroups", MSG.common_title_bundleGroups(), + IconEnum.BUNDLE_GROUP); + + private final Set<Permission> globalPermissions; + + /** + * Creates a new list view. + * + * @param globalPermissions if perms is null, no button actions will be shown in the table + */ + public BundleGroupsListView(Set<Permission> globalPermissions) { + this(null, globalPermissions); + } + + public BundleGroupsListView(Criteria criteria, Set<Permission> globalpermissions) { + super(MSG.common_title_bundleGroups(), criteria); + this.globalPermissions = globalpermissions; + setHeaderIcon(IconEnum.BUNDLE_GROUP.getIcon24x24Path()); + setDataSource(new BundleGroupsDataSource()); + } + + @Override + protected void configureTable() { + ListGridField idField = new ListGridField(BundleGroupsDataSource.FIELD_ID, MSG.common_title_id()); + idField.setType(ListGridFieldType.INTEGER); + idField.setWidth("50"); + + ListGridField nameField = new ListGridField(BundleGroupsDataSource.FIELD_NAME, MSG.common_title_name()); + nameField.setWidth("33%"); + nameField.setCellFormatter(new CellFormatter() { + public String format(Object value, ListGridRecord record, int i, int i1) { + return "<a href="" + record.getAttribute(BundlesWithLatestVersionDataSource.FIELD_NAMELINK) + "">" + + StringUtility.escapeHtml(String.valueOf(value)) + "</a>"; + } + }); + + ListGridField descField = new ListGridField(BundleGroupsDataSource.FIELD_DESCRIPTION, + MSG.common_title_description()); + descField.setWidth("*"); + descField.setCellFormatter(new CellFormatter() { + public String format(Object value, ListGridRecord record, int i, int i1) { + return StringUtility.escapeHtml(String.valueOf(value)); + } + }); + + setListGridFields(idField, nameField, descField); + + setListGridDoubleClickHandler(new DoubleClickHandler() { + @Override + public void onDoubleClick(DoubleClickEvent event) { + ListGrid listGrid = (ListGrid) event.getSource(); + ListGridRecord[] selectedRows = listGrid.getSelectedRecords(); + if (selectedRows != null && selectedRows.length == 1) { + String selectedId = selectedRows[0].getAttribute(BundleGroupsDataSource.FIELD_ID); + CoreGUI.goToView(LinkManager.getBundleGroupLink(Integer.valueOf(selectedId))); + } + } + }); + + boolean hasAuth = globalPermissions.contains(Permission.MANAGE_BUNDLE_GROUPS); + + addTableAction(MSG.common_button_new(), null, new AbstractTableAction((hasAuth) ? TableActionEnablement.ALWAYS + : TableActionEnablement.NEVER) { + public void executeAction(ListGridRecord[] selection, Object actionValue) { + newDetails(); + } + }); + + addTableAction(MSG.common_button_delete(), MSG.view_bundleGroup_deleteConfirm(), new AbstractTableAction( + (hasAuth) ? TableActionEnablement.ANY : TableActionEnablement.NEVER) { + public void executeAction(ListGridRecord[] selections, Object actionValue) { + if (selections == null || selections.length == 0) { + return; + } + + BundleGroupsDataSource ds = (BundleGroupsDataSource) getDataSource(); + final ArrayList<String> doomedNames = new ArrayList<String>(selections.length); + int[] doomedIds = new int[selections.length]; + int i = 0; + for (ListGridRecord selection : selections) { + BundleGroup object = ds.copyValues(selection); + doomedNames.add(object.getName()); + doomedIds[i++] = object.getId(); + } + + BundleGWTServiceAsync bundleManager = GWTServiceLookup.getBundleService(); + bundleManager.deleteBundleGroups(doomedIds, new AsyncCallback<Void>() { + public void onFailure(Throwable caught) { + String names = doomedNames.toString(); + String error = ErrorHandler.getAllMessages(caught); + Message m = new Message(MSG.view_bundle_list_deletesFailure(), names + "<br/>\n" + error, + Severity.Error); + CoreGUI.getMessageCenter().notify(m); + } + + public void onSuccess(Void result) { + Message m = new Message(MSG.view_bundle_list_deletesSuccessful(), doomedNames.toString(), + Severity.Info); + CoreGUI.getMessageCenter().notify(m); + CoreGUI.refresh(); + } + }); + } + }); + } + + @Override + public void newDetails() { + // protect against the fact that we may not have a basepath set if we have not been navigated to directly + // (for example, we may be in a section stack) + if (null != getBasePath()) { + super.newDetails(); + } else { + CoreGUI.goToView(LinkManager.getBundleGroupLink(0)); + } + } + + @Override + public Canvas getDetailsView(Integer bundleGroupId) { + return new BundleGroupEditView(globalPermissions, bundleGroupId); + } + + @Override + public ViewName getViewName() { + return VIEW_ID; + } + +} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java index 109a5d4..d8b66c8 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java @@ -73,7 +73,7 @@ public class BundlesListView extends Table<BundlesWithLatestVersionDataSource> { }
public BundlesListView(Criteria criteria, Set<Permission> perms) { - super(MSG.view_bundle_bundles(), criteria, IconEnum.BUNDLE.getIcon24x24Path()); + super(MSG.common_title_bundles(), criteria, IconEnum.BUNDLE.getIcon24x24Path()); this.permissions = perms; setHeaderIcon(IconEnum.BUNDLE.getIcon24x24Path()); setDataSource(new BundlesWithLatestVersionDataSource()); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java index 2a45f65..3c73e17 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java @@ -102,4 +102,11 @@ public interface BundleGWTService extends RemoteService { boolean isCleanDeployment) throws RuntimeException;
void purgeBundleDestination(int bundleDestinationId) throws RuntimeException; + + BundleGroup createBundleGroup(BundleGroup bundleGroup) throws RuntimeException; + + void deleteBundleGroups(int[] bundleGroupIds) throws RuntimeException; + + BundleGroup updateBundleGroup(BundleGroup bundleGroup) throws RuntimeException; + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java index 7098a1b..9aa5297 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/report/tag/TaggedView.java @@ -120,7 +120,7 @@ public class TaggedView extends EnhancedVLayout implements BookmarkableView, Has
BundlesListView bundlesView = new BundlesListView(criteria, null); viewsWithTags.add(bundlesView); - tab = new Tab(MSG.view_bundle_bundles()); + tab = new Tab(MSG.common_title_bundles()); tab.setIcon(ImageManager.getBundleIcon()); tab.setPane(bundlesView); container.addTab(tab); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java index 01b17a1..40955d4 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java @@ -73,6 +73,16 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override + public BundleGroup createBundleGroup(BundleGroup bundleGroup) throws RuntimeException { + try { + BundleGroup results = bundleManager.createBundleGroup(getSessionSubject(), bundleGroup); + return SerialUtility.prepare(results, "createBundleGroup"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override public BundleVersion createBundleVersionViaRecipe(String recipe) throws RuntimeException { try { BundleVersion results = bundleManager.createBundleVersionViaRecipe(getSessionSubject(), recipe); @@ -128,6 +138,15 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override + public void deleteBundleGroups(int[] bundleGroupIds) throws RuntimeException { + try { + bundleManager.deleteBundleGroups(getSessionSubject(), bundleGroupIds); + } catch (Throwable t) { + throw getExceptionToThrowToClient(t); + } + } + + @Override public void deleteBundleDeployment(int bundleDeploymentId) throws RuntimeException { try { bundleManager.deleteBundleDeployment(getSessionSubject(), bundleDeploymentId); @@ -309,4 +328,15 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund throw getExceptionToThrowToClient(t); } } + + @Override + public BundleGroup updateBundleGroup(BundleGroup bundleGroup) throws RuntimeException { + try { + BundleGroup results = bundleManager.updateBundleGroup(getSessionSubject(), bundleGroup); + return SerialUtility.prepare(results, "updateBundleGroup"); + } catch (Throwable t) { + throw getExceptionToThrowToClient(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 67ec087..21fc3bb 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 @@ -1181,8 +1181,8 @@ view_autoDiscoveryQ_unignoreFailure = Failed to unignore Resources view_autoDiscoveryQ_unignoreInProgress = Unignoring the selected Resources... view_autoDiscoveryQ_unignoreSuccessful = You have successfully unignored the selected Resources. view_autoDiscoveryQ_uninventoried = Uninventoried +view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. view_bundleVersion_loadFailure = Failed to load bundle version data -view_bundle_bundle = Bundle view_bundle_bundleDeployment = Bundle Deployment view_bundle_bundleDeployments = Bundle Deployments view_bundle_bundleDestinations = Bundle Destinations @@ -1190,7 +1190,6 @@ view_bundle_bundleFiles = Bundle Files view_bundle_bundleType = Bundle Type view_bundle_bundleVersion = Bundle Version view_bundle_bundleVersions = Bundle Versions -view_bundle_bundles = Bundles view_bundle_createWizard_bundleDistro = Bundle Distribution view_bundle_createWizard_cancelFailure = Failed to fully cancel the creation of bundle [{0}], version = [{1}] - the bundle may still exist in the database view_bundle_createWizard_cancelSuccessful = Canceled the creation of bundle [{0}], version = [{1}] @@ -1310,6 +1309,7 @@ view_bundle_dest_revertConfirm = This will revert all remote machines back to th view_bundle_dest_tagUpdateFailure = Failed to update bundle destination tags view_bundle_dest_tagUpdateSuccessful = You have successfully updated the bundle destination tags view_bundle_destinations = Destinations +view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = File Size view_bundle_fileListView_loadFailure = Failed to load bundle file data view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties index 2c97c84..4826b90 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_cs.properties @@ -1195,8 +1195,8 @@ view_autoDiscoveryQ_unignoreFailure = Nepodařilo se odignorovat zdroje view_autoDiscoveryQ_unignoreInProgress = Odignorování vybraných zdrojů právě probíhá... view_autoDiscoveryQ_unignoreSuccessful = Vybrané zdroje byly úspěšně odignorovány. view_autoDiscoveryQ_uninventoried = Odinventarizovaný +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. view_bundleVersion_loadFailure = Nepodařilo se načíst data verzí balíků -view_bundle_bundle = Balík view_bundle_bundleDeployment = Nasazení balíku view_bundle_bundleDeployments = Nasazování balíků view_bundle_bundleDestinations = Cíle balíku @@ -1204,7 +1204,6 @@ view_bundle_bundleFiles = Soubory balíku view_bundle_bundleType = Typ balíku view_bundle_bundleVersion = Verze balíku view_bundle_bundleVersions = Verze balíku -view_bundle_bundles = Balíky view_bundle_createWizard_bundleDistro = Distribuce balíku view_bundle_createWizard_cancelFailure = Nepodařilo se zrušit vytváření balíku [{0}], verze = [{1}] - balík může stále existovat v databázi view_bundle_createWizard_cancelSuccessful = Zrušeno vytváření balíku [{0}], verze = [{1}] @@ -1324,6 +1323,7 @@ view_bundle_dest_revertConfirm = Tato volba vrátí stav všech vzdálených str view_bundle_dest_tagUpdateFailure = Nepodařilo se změnit tagy cíle balíku view_bundle_dest_tagUpdateSuccessful = Úspěšně jste změnili tagy cíle balíku view_bundle_destinations = Cíle +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = Velikost souboru view_bundle_fileListView_loadFailure = Nepodařilo se načíst data balíků view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties index d4f053b..2a67608 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_de.properties @@ -1099,8 +1099,8 @@ view_autoDiscoveryQ_unignore = Ignorieren aufheben view_autoDiscoveryQ_unignoreFailure = Konnte das Ignorieren für die Ressourcen nicht aufheben. view_autoDiscoveryQ_unignoreSuccessful = Sie haben erfolgreich das Ignorieren der ausgewählten Ressourcen aufgehoben. view_autoDiscoveryQ_uninventoried = Aus dem Inventory gelöscht +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. ##view_bundleVersion_loadFailure = Failed to load bundle version data -view_bundle_bundle = Bundle ##view_bundle_bundleDeployment = Bundle Deployment ##view_bundle_bundleDeployments = Bundle Deployments view_bundle_bundleDestinations = Bundle-Ziele @@ -1108,7 +1108,6 @@ view_bundle_bundleFiles = Bundle-Dateien view_bundle_bundleType = Bundle-Type view_bundle_bundleVersion = Bundle-Version view_bundle_bundleVersions = Bundle-Versionen -view_bundle_bundles = Bundles ##view_bundle_createWizard_bundleDistro = Bundle Distribution ##view_bundle_createWizard_cancelFailure = Failed to fully cancel the creation of bundle [{0}], version=[{1}] - the bundle may still exist in the database ##view_bundle_createWizard_cancelSuccessful = Canceled the creation of bundle [{0}], version=[{1}] @@ -1216,6 +1215,7 @@ view_bundle_dest_group = Gruppe ##view_bundle_dest_tagUpdateFailure = Failed to update bundle destination tags ##view_bundle_dest_tagUpdateSuccessful = You have successfully updated the bundle destination tags view_bundle_destinations = Ziele +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = Dateigröße ##view_bundle_fileListView_loadFailure = Failed to load bundle file data view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties index c7c1f0a..5f53171 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ja.properties @@ -1171,8 +1171,8 @@ view_autoDiscoveryQ_unignoreFailure = リソースを無視解除のに失敗し view_autoDiscoveryQ_unignoreInProgress = 選択されたリソースの無視を解除中です... view_autoDiscoveryQ_unignoreSuccessful = 選択したリソースの無視解除に成功しました view_autoDiscoveryQ_uninventoried = インベントリ登録をしない +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. view_bundleVersion_loadFailure = バンドルバージョンデータをロードするのに失敗しました -view_bundle_bundle = バンドル view_bundle_bundleDeployment = バンドルデプロイメント view_bundle_bundleDeployments = バンドルデプロイメント view_bundle_bundleDestinations = バンドル宛先 @@ -1180,7 +1180,6 @@ view_bundle_bundleFiles = バンドルファイル view_bundle_bundleType = バンドルタイプ view_bundle_bundleVersion = バンドルバージョン view_bundle_bundleVersions = バンドルバージョン -view_bundle_bundles = バンドル view_bundle_createWizard_bundleDistro = バンドル配布 view_bundle_createWizard_cancelFailure = バンドル [{0}], バージョン = [{1}] の作成の完全なキャンセルに失敗しました - バンドルはデータベースにまだ残っているかもしれません view_bundle_createWizard_cancelSuccessful = バンドル [{0}], バージョン = [{1}] の作成をキャンセルしました @@ -1301,6 +1300,7 @@ view_bundle_dest_revertConfirm = これはすべてのリモートマシンを view_bundle_dest_tagUpdateFailure = バンドル宛先タグの更新に失敗しました view_bundle_dest_tagUpdateSuccessful = バンドル宛先タグの更新に成功しました view_bundle_destinations = 宛先 +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = ファイルサイズ view_bundle_fileListView_loadFailure = バンドルファイルデータをロードするのに失敗しました view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties index 0213540..e41b243 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ko.properties @@ -1054,15 +1054,14 @@ view_autoDiscoveryQ_unignoreFailure = 리소스를 무시 안하는데 실패했 view_autoDiscoveryQ_unignoreInProgress = 선택된 리소스를 무시 안하는중... view_autoDiscoveryQ_unignoreSuccessful = 선택된 리소스를 무시 안하는데 성공했습니다. view_autoDiscoveryQ_uninventoried = 인벤토리 해제 +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. view_bundleVersion_loadFailure = 번들 버전 데이터를 로드하는데 실패했습니다. -view_bundle_bundle = 번들 view_bundle_bundleDeployment = 번들 배포 view_bundle_bundleDeployments = 번들 배포 view_bundle_bundleDestinations = 번들 대상 view_bundle_bundleFiles = 번들 파일 view_bundle_bundleVersion = 번들 버전 view_bundle_bundleVersions = 번들 버전 -view_bundle_bundles = 번들 view_bundle_createWizard_bundleDistro = 번들 배포 view_bundle_createWizard_cancelSuccessful = 번들 [{0}], 버전 = [{1}]의 생성을 취소했습니다. view_bundle_createWizard_clickToUploadRecipe = 레시피 파일을 로드하기 위해 클릭하십시오 @@ -1156,6 +1155,7 @@ view_bundle_dest_purgeFailure = 원격 컴퓨터의 일부 또는 전부에서 view_bundle_dest_purgeSuccessful = 원격 컴퓨터의 일부 또는 전부에서 번들 대상 [{0}]의 제거에 성공했습니다. view_bundle_dest_revertConfirm = 이것은 모든 원격 컴퓨터를 이번 번들 배포로 되돌립니다. 이것을 수행하시겠습니까? view_bundle_destinations = 대상 +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = 파일 크기 view_bundle_fileListView_loadFailure = 번들 파일 데이터 로드에 실패했습니다 view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties index 952b01f..d5c7243 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_pt.properties @@ -1183,8 +1183,8 @@ view_autoDiscoveryQ_unignoreFailure = Falha ao reimportar os recursos view_autoDiscoveryQ_unignoreInProgress = Removendo status de recurso ignorado... view_autoDiscoveryQ_unignoreSuccessful = Status de recurso ignorado removido com sucesso para os recursos selecionados. view_autoDiscoveryQ_uninventoried = Removido do invent\u00E1rio +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. view_bundleVersion_loadFailure = Falha ao carregar dados da vers\u00E3o do bundle -view_bundle_bundle = Bundle view_bundle_bundleDeployment = Implanta\u00E7\u00E3o do Bundle view_bundle_bundleDeployments = Implanta\u00E7\u00F5es do Bundle view_bundle_bundleDestinations = Destina\u00E7\u00E3o do Bundle @@ -1192,7 +1192,6 @@ view_bundle_bundleFiles = Arquivos do Bundle view_bundle_bundleType = Tipo de Bundle view_bundle_bundleVersion = Vers\u00E3o do Bundle view_bundle_bundleVersions = Vers\u00F5es do Bundle -view_bundle_bundles = Bundles view_bundle_createWizard_bundleDistro = Distribui\u00E7\u00E3o do Bundle view_bundle_createWizard_cancelFailure = Falha ao cancelar a cria\u00E7\u00E3o do bundle [{0}], vers\u00E3o = [{1}] - talvez o bundle ainda esteja gravado no banco de dados view_bundle_createWizard_cancelSuccessful = Cria\u00E7\u00E3o do bundle [{0}] cancelada, vers\u00E3o = [{1}] @@ -1312,6 +1311,7 @@ view_bundle_dest_revertConfirm = Esta opera\u00E7\u00E3o reverte todas as m\u00E view_bundle_dest_tagUpdateFailure = Falha ao atualizar as tags para esta destina\u00E7\u00E3o view_bundle_dest_tagUpdateSuccessful = Tags atualizadas com sucesso para esta destina\u00E7\u00E3o! view_bundle_destinations = Destina\u00E7\u00F5es +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = Tamanho do Arquivo view_bundle_fileListView_loadFailure = Falha ao carregar dados do arquivo de bundle view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties index 4fbef12..d88a392 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_ru.properties @@ -2696,6 +2696,7 @@ view_adminTopology_partitionEvents = События раздела view_adminTopology_remoteAgentInstall = Установка удаленного агента view_adminTopology_servers = Серверы view_adminUsersDetails_dataTypeName = пользователь +##view_adminUsers_failCreateUserWithExistingName = Failed to create user with existing name [{0}]. Please use another name. view_admin_administration = Администрация view_admin_configuration = Конфигурация view_admin_content = Контент @@ -2753,6 +2754,8 @@ view_admin_systemSettings_LDAPBindPW_name = Пароль ##view_alert_details_field_watched_resource = Watched Resource ##view_autoDiscoveryQ_field_inventoryStatus = Inventory Status ##view_autoDiscoveryQ_ignore = Ignore +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. ##view_bundle_revertWizard_getInfoStep_revertDeployDescFull = [REVERT From] {0} [REVERT To] {1} ##view_configEdit_description = Description ##view_configEdit_property = Vlastnost diff --git a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties index 24ea681..14d4f90 100644 --- a/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties +++ b/modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages_zh.properties @@ -1168,8 +1168,8 @@ view_autoDiscoveryQ_unignoreFailure = Failed to unignore resources view_autoDiscoveryQ_unignoreInProgress = Unignoring the selected Resources... view_autoDiscoveryQ_unignoreSuccessful = \u6210\u529f\u4f7f\u9009\u4e2d\u7684\u8d44\u6e90\u751f\u6548. view_autoDiscoveryQ_uninventoried = Uninventoried +##view_bundleGroup_deleteConfirm = Are you sure you want to delete this bundle group? Bundles for which this is the only assigned bundle group will become unassigned, and will require global View Bundles permission to view. view_bundleVersion_loadFailure = \u52a0\u8f7dbundle\u7248\u672c\u6570\u636e\u5931\u8d25 -view_bundle_bundle = Bundle view_bundle_bundleDeployment = Bundle\u53d1\u5e03 view_bundle_bundleDeployments = Bundle\u53d1\u5e03 view_bundle_bundleDestinations = Bundle\u76ee\u7684\u5730 @@ -1177,7 +1177,6 @@ view_bundle_bundleFiles = Bundle\u6587\u4ef6 view_bundle_bundleType = Bundle\u7c7b\u578b view_bundle_bundleVersion = Bundle\u7248\u672c view_bundle_bundleVersions = Bundle\u7248\u672c -view_bundle_bundles = Bundles view_bundle_createWizard_bundleDistro = Bundle\u53d1\u5e03 view_bundle_createWizard_cancelFailure = Failed to fully cancel the creation of bundle [{0}], version = [{1}] - the bundle may still exist in the database view_bundle_createWizard_cancelSuccessful = Canceled the creation of bundle [{0}], version = [{1}] @@ -1297,6 +1296,7 @@ view_bundle_dest_revertConfirm = This will revert all remote machines back to th view_bundle_dest_tagUpdateFailure = \u66f4\u65b0bundle\u76ee\u7684\u5730\u6807\u7b7e\u5931\u8d25 view_bundle_dest_tagUpdateSuccessful = You have successfully updated the bundle destination tags view_bundle_destinations = \u76ee\u7684\u5730 +##view_bundle_fail_existingName = Failed to create [{0}]. The name is already being used. Please try another name. view_bundle_fileListView_fileSize = \u6587\u4ef6\u5927\u5c0f view_bundle_fileListView_loadFailure = \u52a0\u8f7dbundle\u6587\u4ef6\u5931\u8d25 view_bundle_fileListView_md5 = MD5 diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java index cfb5cc1..43e1bd9 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java @@ -1330,9 +1330,12 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
subject = createSession(subject); // start a session so we can use this subject in SLSB calls
+ BundleGroup bundleGroup = new BundleGroup(TEST_BUNDLE_GROUP_NAME); + bundleGroup.setDescription("test"); + // deny bundle group create try { - bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME, "test"); + bundleManager.createBundleGroup(subject, bundleGroup); fail("Should have thrown PermissionException"); } catch (PermissionException e) { // expected @@ -1340,7 +1343,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// allow bundle group create addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - BundleGroup bundleGroup = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME, "test"); + bundleGroup = bundleManager.createBundleGroup(subject, bundleGroup);
// deny bundle group delete removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); @@ -1413,7 +1416,11 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// deny global perm bundle assign addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - bundleGroup = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME, "test"); + + bundleGroup = new BundleGroup(TEST_BUNDLE_GROUP_NAME); + bundleGroup.setDescription("test"); + + bundleGroup = bundleManager.createBundleGroup(subject, bundleGroup); removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
try { @@ -1538,7 +1545,9 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// create bundle group addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - BundleGroup bundleGroup1 = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME + "_1", "bg-1"); + BundleGroup bundleGroup1 = new BundleGroup(TEST_BUNDLE_GROUP_NAME + "_1"); + bundleGroup1.setDescription("bg-1"); + bundleGroup1 = bundleManager.createBundleGroup(subject, bundleGroup1); removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
// add bg1 to the role, but no perms @@ -1578,7 +1587,9 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// create second bundle group addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - BundleGroup bundleGroup2 = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME + "_2", "bg-2"); + BundleGroup bundleGroup2 = new BundleGroup(TEST_BUNDLE_GROUP_NAME + "_2"); + bundleGroup2.setDescription("bg-2"); + bundleGroup2 = bundleManager.createBundleGroup(subject, bundleGroup2); removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
// deny bundle create in bg2 (not associated with role) @@ -1676,7 +1687,9 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// create bundle group addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - BundleGroup bundleGroup1 = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME + "_1", "bg-1"); + BundleGroup bundleGroup1 = new BundleGroup(TEST_BUNDLE_GROUP_NAME + "_1"); + bundleGroup1.setDescription("bg-1"); + bundleGroup1 = bundleManager.createBundleGroup(subject, bundleGroup1); removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
// add bg1 to the role with group create @@ -1719,7 +1732,9 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// create bundle group addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - BundleGroup bundleGroup = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME, "bg"); + BundleGroup bundleGroup = new BundleGroup(TEST_BUNDLE_GROUP_NAME); + bundleGroup.setDescription("bg"); + bundleGroup = bundleManager.createBundleGroup(subject, bundleGroup); removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
// add bg to the role with group create @@ -1810,7 +1825,9 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
// create bundle group addRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS); - BundleGroup bundleGroup = bundleManager.createBundleGroup(subject, TEST_BUNDLE_GROUP_NAME, "bg"); + BundleGroup bundleGroup = new BundleGroup(TEST_BUNDLE_GROUP_NAME); + bundleGroup.setDescription("bg"); + bundleGroup = bundleManager.createBundleGroup(subject, bundleGroup); removeRolePermissions(role, Permission.MANAGE_BUNDLE_GROUPS);
// add bg to the role with group create diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java index c2f6048..198018c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java @@ -423,8 +423,8 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote { attachedRole.setPermissions(role.getPermissions()); processDependentPermissions(attachedRole);
- // Then update the subjects, resourceGroups, and/or ldapGroups, but only if those fields are non-null on the - // passed-in Role. + // Then update the subjects, resourceGroups, ldapGroups, and/or bundle groups, but only if those fields are + // non-null on the passed-in Role. Set<Subject> newSubjects = role.getSubjects(); if (newSubjects != null) { Set<Subject> currentSubjects = attachedRole.getSubjects(); @@ -483,10 +483,29 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote { } }
+ Set<BundleGroup> newBundleGroups = role.getBundleGroups(); + if (newBundleGroups != null) { + Set<BundleGroup> currentBundleGroups = attachedRole.getBundleGroups(); + // wrap in new HashSet to avoid ConcurrentModificationExceptions. + Set<BundleGroup> bundleGroupsToRemove = new HashSet<BundleGroup>(currentBundleGroups); + for (BundleGroup bg : currentBundleGroups) { + bundleGroupsToRemove.remove(bg); + } + for (BundleGroup bg : bundleGroupsToRemove) { + attachedRole.removeBundleGroup(bg); + } + + for (BundleGroup bg : newBundleGroups) { + BundleGroup attachedBundleGroup = entityManager.find(BundleGroup.class, bg.getId()); + attachedRole.addBundleGroup(attachedBundleGroup); + } + } + // Fetch the lazy Sets on the Role to be returned. attachedRole.getResourceGroups().size(); attachedRole.getSubjects().size(); attachedRole.getLdapGroups().size(); + attachedRole.getBundleGroups().size();
return attachedRole; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerRemote.java index 83194da..47a7f55 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerRemote.java @@ -45,8 +45,7 @@ public interface RoleManagerRemote { Role getRole(Subject subject, int roleId);
/** - * Persists the new role to the database. The subjects assigned to the role are ignored - this only creates the - * role entity with 0 subjects initially assigned to it. + * Persists the new role to the database. * * @param subject The user attempting to create the role * @param newRole The new role being created @@ -64,7 +63,8 @@ public interface RoleManagerRemote { void deleteRoles(Subject subject, int[] roleIds);
/** - * Updates the given role, excluding the subjects and groups. This updates permissions, name, description, etc. + * Updates the given role including permissions. To update subjects, resource groups, ldap groups + * or bundle groups pass a non-null value. * * @param subject The user updating the role * @param role The role being updated diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java index 986b080..6b4a890 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java @@ -1973,7 +1973,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @RequiredPermission(Permission.MANAGE_BUNDLE_GROUPS) - public BundleGroup createBundleGroup(Subject subject, String name, String description) throws Exception { + public BundleGroup createBundleGroup(Subject subject, BundleGroup bundleGroup) throws Exception { + String name = bundleGroup.getName(); if (null == name || "".equals(name.trim())) { throw new IllegalArgumentException("Invalid bundleGroupName: " + name); } @@ -1986,14 +1987,19 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot + name); }
- // create and add the required Repo. the Repo is a detached object which helps in its eventual - // removal. - BundleGroup bg = new BundleGroup(name); - bg.setDescription(description); + entityManager.persist(bundleGroup);
- entityManager.persist(bg); + Set<Bundle> bundles = bundleGroup.getBundles(); + if (null != bundles) { + int[] bundleIds = new int[bundles.size()]; + int i = 0; + for (Bundle b : bundles) { + bundleIds[i++] = b.getId(); + } + assignBundlesToBundleGroup(subject, bundleGroup.getId(), bundleIds); + }
- return bg; + return bundleGroup; }
@Override @@ -2337,4 +2343,40 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot throw new PermissionException(msg); }
+ @Override + public BundleGroup updateBundleGroup(Subject subject, BundleGroup bundleGroup) throws Exception { + BundleGroup attachedBundleGroup = entityManager.find(BundleGroup.class, bundleGroup.getId()); + if (attachedBundleGroup == null) { + throw new IllegalStateException("Cannot update " + bundleGroup + + ", because no bundle group exists with id [" + bundleGroup.getId() + "]."); + } + + // First update the simple fields and the permissions. + attachedBundleGroup.setName(bundleGroup.getName()); + attachedBundleGroup.setDescription(bundleGroup.getDescription()); + + Set<Bundle> newBundles = bundleGroup.getBundles(); + if (newBundles != null) { + Set<Bundle> currentBundles = attachedBundleGroup.getBundles(); + // wrap in new HashSet to avoid ConcurrentModificationExceptions. + Set<Bundle> BundlesToRemove = new HashSet<Bundle>(currentBundles); + for (Bundle bg : currentBundles) { + BundlesToRemove.remove(bg); + } + for (Bundle bg : BundlesToRemove) { + attachedBundleGroup.removeBundle(bg); + } + + for (Bundle bg : newBundles) { + Bundle attachedBundle = entityManager.find(Bundle.class, bg.getId()); + attachedBundleGroup.addBundle(attachedBundle); + } + } + + // Fetch the lazy Set for the return + attachedBundleGroup.getBundles().size(); + + return attachedBundleGroup; + } + } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java index ee023e8..3eeb3f1 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java @@ -146,7 +146,8 @@ public interface BundleManagerRemote { throws Exception;
/** - * Assign the specified bundles to the specified bundle group. + * Assign the specified bundles to the specified bundle group. This adds bundles that were not previously + * assigned. Others are ignored. * <pre> * Requires VIEW permission for the relevant bundle and one of: * - Global.MANAGE_BUNDLE_GROUPS @@ -206,18 +207,17 @@ public interface BundleManagerRemote { String destBaseDirName, String deployDir, Integer groupId) throws Exception;
/** - * Create a new bundle group. + * Create a new bundle group. Bundles, if specified will be set as the initial bundles in the group. * <pre> * Require Permissions: * - Global.MANAGE_BUNDLE_GROUPS * </pre> * @param subject user that must have proper permissions - * @param name the unique bundle group name - * @param description an optional description + * @param bundleGroup the new bundle group name the unique bundle group name * @return the persisted BundleGroup * @throws Exception */ - BundleGroup createBundleGroup(Subject subject, String name, String description) throws Exception; + BundleGroup createBundleGroup(Subject subject, BundleGroup bundleGroup) throws Exception;
/** * Creates a bundle version based on single recipe string. The recipe specifies the bundle name, @@ -624,7 +624,8 @@ public interface BundleManagerRemote { String deploymentDescription, boolean isCleanDeployment) throws Exception;
/** - * Unassign the specified bundles from the specified bundle group. + * Unassign the specified bundles from the specified bundle group. This removes bundles that were previously + * assigned. Others are ignored. * <pre> * Requires VIEW permission for the relevant bundles and one of: * - Global.MANAGE_BUNDLE_GROUPS @@ -637,4 +638,18 @@ public interface BundleManagerRemote { * @param bundleIds */ void unassignBundlesFromBundleGroup(Subject subject, int bundleGroupId, int[] bundleIds); + + /** + * Updates an existing bundle group. The set of bundles will be updated if non-null. + * <pre> + * Require Permissions: + * - Global.MANAGE_BUNDLE_GROUPS + * </pre> + * @param subject user that must have proper permissions + * @param bundleGroup the updated bundle group + * @return the updated BundleGroup + * @throws Exception + */ + BundleGroup updateBundleGroup(Subject subject, BundleGroup bundleGroup) throws Exception; + }
commit 28ed1b5ab2683ae3b040d163ae5ff7fae8889ed0 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 13 15:01:50 2013 -0400
fix some issues, add some new api methods
diff --git a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml index 40e826a..5182ef1 100644 --- a/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml +++ b/modules/enterprise/server/jar/intentional-api-changes-since-4.8.0.xml @@ -67,7 +67,7 @@ <difference> <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> - <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, java.lang.String, java.lang.String)</method> + <method>org.rhq.core.domain.bundle.BundleGroup createBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
@@ -128,38 +128,45 @@ </difference>
<difference> - <className>org/rhq/enterprise/server/bundle/RoleManagerRemote</className> + <className>org/rhq/enterprise/server/authz/RoleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void addBundleGroupsToRole(org.rhq.core.domain.auth.Subject, int, int[])</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
<difference> - <className>org/rhq/enterprise/server/bundle/RoleManagerRemote</className> + <className>org/rhq/enterprise/server/authz/RoleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void addRolesToBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
<difference> - <className>org/rhq/enterprise/server/bundle/RoleManagerRemote</className> + <className>org/rhq/enterprise/server/authz/RoleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void removeBundleGroupsFromRole(org.rhq.core.domain.auth.Subject, int, int[])</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
<difference> - <className>org/rhq/enterprise/server/bundle/RoleManagerRemote</className> + <className>org/rhq/enterprise/server/authz/RoleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void removeRolesFromBundleGroup(org.rhq.core.domain.auth.Subject, int, int[])</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
<difference> - <className>org/rhq/enterprise/server/bundle/RoleManagerRemote</className> + <className>org/rhq/enterprise/server/authz/RoleManagerRemote</className> <differenceType>7012</differenceType> <!-- method added to an interface --> <method>void setAssignedBundleGroups(org.rhq.core.domain.auth.Subject, int, int[])</method> <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> </difference>
+ <difference> + <className>org/rhq/enterprise/server/bundle/BundleManagerRemote</className> + <differenceType>7012</differenceType> <!-- method added to an interface --> + <method>org.rhq.core.domain.bundle.BundleGroup updateBundleGroup(org.rhq.core.domain.auth.Subject, org.rhq.core.domain.bundle.BundleGroup)</method> + <justification>Adding a method to a remote API interface is safe. This is newly implemented functionality.</justification> + </difference> + </differences>
commit 815bdcf9735149a5b5fd331f02fecbb9977e8ec5 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Aug 13 14:57:52 2013 -0400
up datastax driver version
diff --git a/.classpath b/.classpath index cad0bdb..281a7b3 100644 --- a/.classpath +++ b/.classpath @@ -177,8 +177,6 @@ <classpathentry kind="src" path="modules/plugins/perftest/src/main/java"/> <classpathentry kind="src" path="modules/plugins/perftest/src/test/java"/> <classpathentry kind="src" path="modules/plugins/perftest/target/generated-sources/xjc"/> - <classpathentry kind="src" path="modules/helpers/pluginAnnotations/src/main/java"/> - <classpathentry kind="src" path="modules/helpers/pluginGen/src/main/java"/> <classpathentry kind="src" path="modules/helpers/perftest-support/src/main/java"/> <classpathentry kind="src" path="modules/helpers/rtfilter/src/main/java"/> <classpathentry kind="src" path="modules/core/plugin-container-itest/src/test/java"/> @@ -380,7 +378,7 @@ <classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/byteman/byteman-submit/1.5.2/byteman-submit-1.5.2.jar" sourcepath="M2_REPO/org/jboss/byteman/byteman-submit/1.5.2/byteman-submit-1.5.2-sources.jar"/> <classpathentry exported="true" kind="var" path="M2_REPO/org/jboss/byteman/byteman-bmunit/1.5.2/byteman-bmunit-1.5.2.jar" sourcepath="M2_REPO/org/jboss/byteman/byteman-bmunit/1.5.2/byteman-bmunit-1.5.2-sources.jar"/> <classpathentry kind="var" path="M2_REPO/org/apache/cassandra/cassandra-all/1.2.4/cassandra-all-1.2.4.jar"/> - <classpathentry kind="var" path="M2_REPO/com/datastax/cassandra/cassandra-driver-core/1.0.0-rhq-1.2.4/cassandra-driver-core-1.0.0-rhq-1.2.4.jar"/> + <classpathentry kind="var" path="M2_REPO/com/datastax/cassandra/cassandra-driver-core/1.0.2-rhq-1.2.4/cassandra-driver-core-1.0.2-rhq-1.2.4.jar"/> <classpathentry kind="var" path="M2_REPO/org/apache/thrift/libthrift/0.7.0/libthrift-0.7.0.jar"/> <classpathentry kind="var" path="M2_REPO/commons-cli/commons-cli/1.2/commons-cli-1.2.jar"/> <classpathentry kind="var" path="M2_REPO/com/google/guava/guava/12.0/guava-12.0.jar"/>
rhq-commits@lists.fedorahosted.org