modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundleAgentService.java | 9
modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeRequest.java | 57 +++
modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeResponse.java | 67 +++
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java | 9
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundleFacet.java | 2
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeRequest.java | 67 +++
modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeResult.java | 65 +++
modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java | 60 +++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentView.java | 47 ++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/destination/BundleDestinationView.java | 49 ++
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundlesListView.java | 2
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java | 1
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/GWTServiceLookup.java | 4
modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java | 8
modules/enterprise/gui/coregui/src/main/resources/org/rhq/enterprise/gui/coregui/client/Messages.properties | 8
modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16.png |binary
modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16_Disabled.png |binary
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java | 171 +++++++++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java | 13
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java | 11
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java | 4
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java | 64 +++
modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java | 95 +++++
modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java | 34 +
25 files changed, 815 insertions(+), 34 deletions(-)
New commits:
commit 7f8e62733484bcdf28b48cd7db684f8811ed8ab3
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Jan 13 20:02:24 2011 -0500
log better errors
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 ee39eaa..3f56380 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
@@ -873,18 +873,27 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
bundleDeployment.setErrorMessage(null);
bundleDeployment.setStatus(BundleDeploymentStatus.SUCCESS);
} else {
+ bundleDeployment.setLive(true); // not all deployments are purged - error indicates it is still live somewhere
+
+ StringBuilder errorStr = new StringBuilder();
int totalDeployments = bundleDeployment.getResourceDeployments().size();
int failedPurges = failedToPurge.size();
- bundleDeployment.setLive(true); // not all deployments are purged - error indicates it is still live somewhere
if (failedPurges < totalDeployments) {
bundleDeployment.setStatus(BundleDeploymentStatus.MIXED); // some deployments were purged, so show MIXED status
- bundleDeployment.setErrorMessage("Failed to purge [" + failedPurges + "] of [" + totalDeployments
+ errorStr.append("Failed to purge [" + failedPurges + "] of [" + totalDeployments
+ "] remote resource deployments");
} else {
bundleDeployment.setStatus(BundleDeploymentStatus.FAILURE); // all deployments failed to be purged
- bundleDeployment.setErrorMessage("Failed to purge all [" + failedPurges
- + "] remote resource deployments");
+ errorStr.append("Failed to purge all [" + failedPurges + "] remote resource deployments");
}
+
+ // key is the resource deployment that failed to be purged; value is the error message
+ for (Map.Entry<BundleResourceDeployment, String> entry : failedToPurge.entrySet()) {
+ errorStr.append("\n\n");
+ errorStr.append(entry.getKey().getResource().getName()).append(": ").append(entry.getValue());
+ }
+
+ bundleDeployment.setErrorMessage(errorStr.toString());
}
return;
diff --git a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
index 24b6b72..ca528ea 100644
--- a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
+++ b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
@@ -140,9 +140,13 @@ public class AntBundlePluginComponent implements ResourceComponent, BundleFacet
// Send the diffs to the Server so it can store them as an entry in the deployment history.
BundleManagerProvider bundleManagerProvider = request.getBundleManagerProvider();
DeployDifferences diffs = project.getDeployDifferences();
- // TODO: put the diffs in the "attachment" area and make it more formatted/legible
+
+ String msg = new StringBuilder("Added files=").append(diffs.getAddedFiles().size()).append(
+ "; Deleted files=").append(diffs.getDeletedFiles().size()).append(
+ " (see attached details for more information)").toString();
+ String fullDetails = formatDiff(diffs);
bundleManagerProvider.auditDeployment(resourceDeployment, "Deployment Differences", project.getName(),
- BundleResourceDeploymentHistory.Category.DEPLOY_STEP, null, diffs.toString(), null);
+ BundleResourceDeploymentHistory.Category.DEPLOY_STEP, null, msg, fullDetails);
} catch (Throwable t) {
if (log.isDebugEnabled()) {
try {
@@ -246,4 +250,55 @@ public class AntBundlePluginComponent implements ResourceComponent, BundleFacet
}
return antProps;
}
+
+ private String formatDiff(DeployDifferences diffs) {
+ String indent = " ";
+ String nl = "\n";
+ StringBuilder str = new StringBuilder("DEPLOYMENT DETAILS:");
+ str.append(nl);
+
+ str.append("Added Files: ").append(diffs.getAddedFiles().size()).append(nl);
+ for (String f : diffs.getAddedFiles()) {
+ str.append(indent).append(f).append(nl);
+ }
+
+ str.append("Deleted Files: ").append(diffs.getDeletedFiles().size()).append(nl);
+ for (String f : diffs.getDeletedFiles()) {
+ str.append(indent).append(f).append(nl);
+ }
+
+ str.append("Changed Files: ").append(diffs.getChangedFiles().size()).append(nl);
+ for (String f : diffs.getChangedFiles()) {
+ str.append(indent).append(f).append(nl);
+ }
+
+ str.append("Backed Up Files: ").append(diffs.getBackedUpFiles().size()).append(nl);
+ for (Map.Entry<String, String> entry : diffs.getBackedUpFiles().entrySet()) {
+ str.append(indent).append(entry.getKey()).append(" -> ").append(entry.getValue()).append(nl);
+ }
+
+ str.append("Restored Files: ").append(diffs.getRestoredFiles().size()).append(nl);
+ for (Map.Entry<String, String> entry : diffs.getRestoredFiles().entrySet()) {
+ str.append(indent).append(entry.getKey()).append(" <- ").append(entry.getValue()).append(nl);
+ }
+
+ str.append("Ignored Files: ").append(diffs.getIgnoredFiles().size()).append(nl);
+ for (String f : diffs.getIgnoredFiles()) {
+ str.append(indent).append(f).append(nl);
+ }
+
+ str.append("Realized Files: ").append(diffs.getRealizedFiles().size()).append(nl);
+ for (String f : diffs.getRealizedFiles().keySet()) {
+ str.append(indent).append(f).append(nl);
+ }
+
+ str.append("Was Cleaned?: ").append(diffs.wasCleaned()).append(nl);
+
+ str.append("Errors: ").append(diffs.getErrors().size()).append(nl);
+ for (Map.Entry<String, String> entry : diffs.getErrors().entrySet()) {
+ str.append(indent).append(entry.getKey()).append(" : ").append(entry.getValue()).append(nl);
+ }
+
+ return str.toString();
+ }
}
commit 0d3b7dad5fc2e8b3e496becb4d15425c2070f3ff
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Jan 13 18:53:17 2011 -0500
BZ 645412 finish first attempt at end-to-end bundle purge. still need to test this.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java
index ea8385a..9e28999 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java
@@ -18,12 +18,15 @@
*/
package org.rhq.core.domain.criteria;
+import java.util.List;
+
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.rhq.core.domain.bundle.BundleDeploymentStatus;
import org.rhq.core.domain.bundle.BundleResourceDeployment;
+import org.rhq.core.domain.util.CriteriaUtils;
/**
* @author Jay Shaughnessy
@@ -35,6 +38,7 @@ public class BundleResourceDeploymentCriteria extends Criteria {
private static final long serialVersionUID = 1L;
private Integer filterId;
+ private List<Integer> filterIds; // needs overrides
private Integer filterBundleDeploymentId; // requires override
private String filterBundleDeploymentName; // requires override
private Integer filterResourceId; // requires override
@@ -46,6 +50,7 @@ public class BundleResourceDeploymentCriteria extends Criteria {
private boolean fetchHistories;
public BundleResourceDeploymentCriteria() {
+ filterOverrides.put("ids", "id IN ( ? )");
filterOverrides.put("bundleDeploymentId", "bundleDeployment.id = ?");
filterOverrides.put("bundleDeploymentName", "bundleDeployment.name like ?");
filterOverrides.put("resourceId", "resource.id = ?");
@@ -61,6 +66,10 @@ public class BundleResourceDeploymentCriteria extends Criteria {
this.filterId = filterId;
}
+ public void addFilterIds(Integer... filterIds) {
+ this.filterIds = CriteriaUtils.getListIgnoringNulls(filterIds);
+ }
+
public void addFilterBundleDeploymentId(Integer filterBundleDeploymentId) {
this.filterBundleDeploymentId = filterBundleDeploymentId;
}
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 c0bbe7c..1838e14 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
@@ -87,8 +87,6 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
* @author Greg Hinkle
*/
public class BundleDeploymentView extends LocatableVLayout implements BookmarkableView {
- private BundleGWTServiceAsync bundleService;
-
private BundleDeployment deployment;
private BundleVersion version;
private Bundle bundle;
@@ -211,7 +209,11 @@ public class BundleDeploymentView extends LocatableVLayout implements Bookmarkab
private Canvas getActionLayout(String locatorId) {
LocatableVLayout actionLayout = new LocatableVLayout(locatorId, 10);
- // we can only revert the live deployments, only show revert button when appropriate
+ // we can only revert the live deployments, only show revert button when appropriate
+ // in addition, we provide a purge button if you are viewing the live deployment, so
+ // they can be shown an option to purge the platform content (since only the "live"
+ // deployment represents content on the remote machines, showing purge only for live
+ // deployments makes sense).
if (deployment.isLive()) {
IButton revertButton = new LocatableIButton(actionLayout.extendLocatorId("Revert"), MSG
.view_bundle_revert());
@@ -222,8 +224,44 @@ public class BundleDeploymentView extends LocatableVLayout implements Bookmarkab
}
});
actionLayout.addMember(revertButton);
+
+ IButton purgeButton = new LocatableIButton(actionLayout.extendLocatorId("Purge"), MSG.view_bundle_purge());
+ purgeButton.setIcon("subsystems/bundle/BundleDestinationAction_Purge_16.png");
+ purgeButton.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
+ public void onClick(com.smartgwt.client.widgets.events.ClickEvent clickEvent) {
+ SC.ask(MSG.view_bundle_dest_purgeConfirm(), new BooleanCallback() {
+ public void execute(Boolean aBoolean) {
+ if (aBoolean) {
+ final int destinationId = deployment.getDestination().getId();
+ final String destinationName = deployment.getDestination().getName();
+ BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService(600000); // 10m should be enough right?
+ bundleService.purgeBundleDestination(destinationId, new AsyncCallback<Void>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(
+ MSG.view_bundle_dest_purgeFailure(destinationName), caught);
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_bundle_dest_purgeSuccessful(destinationName),
+ Message.Severity.Info));
+ // Bundle destination is purged, go back to bundle deployment view - it is not live anymore
+ CoreGUI.goToView(LinkManager.getBundleDeploymentLink(bundle.getId(), deployment
+ .getId()), true);
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+ actionLayout.addMember(purgeButton);
+
if (!canManageBundles) {
revertButton.setDisabled(true);
+ purgeButton.setDisabled(true);
}
}
@@ -235,6 +273,7 @@ public class BundleDeploymentView extends LocatableVLayout implements Bookmarkab
SC.ask(MSG.view_bundle_deploy_deleteConfirm(), new BooleanCallback() {
public void execute(Boolean aBoolean) {
if (aBoolean) {
+ BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
bundleService.deleteBundleDeployment(deployment.getId(), new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
@@ -385,7 +424,7 @@ public class BundleDeploymentView extends LocatableVLayout implements Bookmarkab
criteria.fetchDestination(true);
criteria.fetchTags(true);
- bundleService = GWTServiceLookup.getBundleService();
+ final BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
bundleService.findBundleDeploymentsByCriteria(criteria, new AsyncCallback<PageList<BundleDeployment>>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_bundle_deploy_loadFailure(), caught);
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 d471742..e01ae47 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
@@ -66,8 +66,6 @@ import org.rhq.enterprise.gui.coregui.client.util.selenium.LocatableVLayout;
* @author Greg Hinkle
*/
public class BundleDestinationView extends LocatableVLayout implements BookmarkableView {
- private BundleGWTServiceAsync bundleService;
-
private BundleDestination destination;
private Bundle bundle;
@@ -207,6 +205,7 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
SC.ask(MSG.view_bundle_dest_purgeConfirm(), new BooleanCallback() {
public void execute(Boolean aBoolean) {
if (aBoolean) {
+ BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService(600000); // 10m should be enough right?
bundleService.purgeBundleDestination(destination.getId(), new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
@@ -238,6 +237,7 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
SC.ask(MSG.view_bundle_dest_deleteConfirm(), new BooleanCallback() {
public void execute(Boolean aBoolean) {
if (aBoolean) {
+ BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
bundleService.deleteBundleDestination(destination.getId(), new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
@@ -288,7 +288,7 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
criteria.fetchDeployments(true);
criteria.fetchTags(true);
- bundleService = GWTServiceLookup.getBundleService();
+ BundleGWTServiceAsync bundleService = GWTServiceLookup.getBundleService();
bundleService.findBundleDestinationsByCriteria(criteria, new AsyncCallback<PageList<BundleDestination>>() {
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_bundle_dest_loadFailure(), caught);
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/GWTServiceLookup.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/GWTServiceLookup.java
index d675373..1e8a94e 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/GWTServiceLookup.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/GWTServiceLookup.java
@@ -102,6 +102,10 @@ public class GWTServiceLookup {
return secure(BundleGWTServiceAsync.Util.getInstance());
}
+ public static BundleGWTServiceAsync getBundleService(int timeout) {
+ return secure(BundleGWTServiceAsync.Util.getInstance(), timeout);
+ }
+
public static ResourceBossGWTServiceAsync getResourceBossService() {
return secure(ResourceBossGWTServiceAsync.Util.getInstance());
}
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 0f99049..ee39eaa 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
@@ -45,6 +45,8 @@ import org.apache.commons.logging.LogFactory;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.rhq.core.clientapi.agent.bundle.BundleAgentService;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeRequest;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeResponse;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleRequest;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleResponse;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUtility;
@@ -80,9 +82,11 @@ import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.StringUtils;
import org.rhq.core.util.NumberUtil;
+import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.agentclient.AgentClient;
@@ -778,23 +782,112 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
+ @TransactionAttribute(TransactionAttributeType.NEVER)
public void purgeBundleDestination(Subject subject, int bundleDestinationId) throws Exception {
- BundleDeploymentCriteria c = new BundleDeploymentCriteria();
- c.addFilterDestinationId(bundleDestinationId);
- c.addFilterIsLive(true);
- c.fetchBundleVersion(true);
- c.fetchResourceDeployments(true);
- c.fetchDestination(true);
- List<BundleDeployment> liveDeployments = bundleManager.findBundleDeploymentsByCriteria(subject, c);
+ // find the live bundle deployment for this destination, and get all the resource deployments for that live deployment
+ BundleDeploymentCriteria bdc = new BundleDeploymentCriteria();
+ bdc.addFilterDestinationId(bundleDestinationId);
+ bdc.addFilterIsLive(true);
+ bdc.fetchBundleVersion(true);
+ bdc.fetchResourceDeployments(true);
+ bdc.fetchDestination(true);
+ List<BundleDeployment> liveDeployments = bundleManager.findBundleDeploymentsByCriteria(subject, bdc);
if (1 != liveDeployments.size()) {
throw new IllegalArgumentException("No live deployment to purge is found for destinationId ["
+ bundleDestinationId + "]");
}
BundleDeployment liveDeployment = liveDeployments.get(0);
- BundleDestination destination = liveDeployment.getDestination();
List<BundleResourceDeployment> resourceDeploys = liveDeployment.getResourceDeployments();
+ if (resourceDeploys == null || resourceDeploys.isEmpty()) {
+ return; // nothing to do
+ }
+
+ // we need to obtain the bundle type (the remote plugin container needs it). our first criteria can't fetch this deep, we have to do another query.
+ BundleVersionCriteria bvc = new BundleVersionCriteria();
+ bvc.addFilterId(liveDeployment.getBundleVersion().getId());
+ bvc.fetchBundle(true); // will eagerly fetch the bundle type
+ PageList<BundleVersion> bvs = bundleManager.findBundleVersionsByCriteria(subject, bvc);
+ liveDeployment.setBundleVersion(bvs.get(0)); // wire up the full bundle version back into the live deployment
- // TODO loop through each deployment and purge it on agent
+ // we need to obtain the resources for all resource deployments - our first criteria can't fetch this deep, we have to do another query.
+ List<Integer> resourceDeployIds = new ArrayList<Integer>();
+ for (BundleResourceDeployment resourceDeploy : resourceDeploys) {
+ resourceDeployIds.add(resourceDeploy.getId());
+ }
+ BundleResourceDeploymentCriteria brdc = new BundleResourceDeploymentCriteria();
+ brdc.addFilterIds(resourceDeployIds.toArray(new Integer[resourceDeployIds.size()]));
+ brdc.fetchResource(true);
+ brdc.setPageControl(PageControl.getUnlimitedInstance());
+ PageList<BundleResourceDeployment> brdResults = bundleManager.findBundleResourceDeploymentsByCriteria(subject,
+ brdc);
+ resourceDeploys.clear();
+ resourceDeploys.addAll(brdResults);
+ // need to wire the live bundle deployment back in - no need for another query or fetch it above because we have it already
+ for (BundleResourceDeployment brd : brdResults) {
+ brd.setBundleDeployment(liveDeployment);
+ }
+
+ // loop through each deployment and purge it on agent
+ Map<BundleResourceDeployment, String> failedToPurge = new HashMap<BundleResourceDeployment, String>();
+ for (BundleResourceDeployment resourceDeploy : resourceDeploys) {
+ try {
+ Subject overlord = subjectManager.getOverlord();
+ AgentClient agentClient = agentManager.getAgentClient(overlord, resourceDeploy.getResource().getId());
+ BundleAgentService bundleAgentService = agentClient.getBundleAgentService();
+ BundlePurgeRequest request = new BundlePurgeRequest(resourceDeploy);
+ BundlePurgeResponse results = bundleAgentService.purge(request);
+ if (!results.isSuccess()) {
+ String errorMessage = results.getErrorMessage();
+ failedToPurge.put(resourceDeploy, errorMessage);
+ }
+ } catch (Exception e) {
+ String errorMessage = ThrowableUtil.getStackAsString(e);
+ failedToPurge.put(resourceDeploy, errorMessage);
+ }
+ }
+
+ // marks the live deployment "no longer live"
+ bundleManager._finalizePurge(subject, liveDeployment, failedToPurge);
+
+ // throw an exception if we failed to purge one or more resource deployments.
+ // since we are not in a tx context, we lose nothing. All DB updates have already been committed by now
+ // which is what we want. All this does is inform the caller something went wrong.
+ if (!failedToPurge.isEmpty()) {
+ int totalDeployments = liveDeployment.getResourceDeployments().size();
+ int failedPurges = failedToPurge.size();
+ throw new Exception("Failed to purge [" + failedPurges + "] of [" + totalDeployments
+ + "] remote resource deployments");
+ }
+ return;
+ }
+
+ @Override
+ @RequiredPermission(Permission.MANAGE_SECURITY)
+ // no one should be calling us except overlord
+ public void _finalizePurge(Subject subject, BundleDeployment bundleDeployment,
+ Map<BundleResourceDeployment, String> failedToPurge) throws Exception {
+
+ bundleDeployment = entityManager.find(BundleDeployment.class, bundleDeployment.getId());
+ if (failedToPurge.isEmpty()) {
+ bundleDeployment.setLive(false); // all deployments are purged, no where is this live anymore
+ bundleDeployment.setErrorMessage(null);
+ bundleDeployment.setStatus(BundleDeploymentStatus.SUCCESS);
+ } else {
+ int totalDeployments = bundleDeployment.getResourceDeployments().size();
+ int failedPurges = failedToPurge.size();
+ bundleDeployment.setLive(true); // not all deployments are purged - error indicates it is still live somewhere
+ if (failedPurges < totalDeployments) {
+ bundleDeployment.setStatus(BundleDeploymentStatus.MIXED); // some deployments were purged, so show MIXED status
+ bundleDeployment.setErrorMessage("Failed to purge [" + failedPurges + "] of [" + totalDeployments
+ + "] remote resource deployments");
+ } else {
+ bundleDeployment.setStatus(BundleDeploymentStatus.FAILURE); // all deployments failed to be purged
+ bundleDeployment.setErrorMessage("Failed to purge all [" + failedPurges
+ + "] remote resource deployments");
+ }
+ }
+
+ return;
}
@Override
@@ -1178,10 +1271,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override
public PageList<BundleDeployment> findBundleDeploymentsByCriteria(Subject subject, BundleDeploymentCriteria criteria) {
-
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- ;
-
CriteriaQueryRunner<BundleDeployment> queryRunner = new CriteriaQueryRunner<BundleDeployment>(criteria,
generator, entityManager);
return queryRunner.execute();
@@ -1191,8 +1281,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
public PageList<BundleDestination> findBundleDestinationsByCriteria(Subject subject,
BundleDestinationCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- ;
-
CriteriaQueryRunner<BundleDestination> queryRunner = new CriteriaQueryRunner<BundleDestination>(criteria,
generator, entityManager);
return queryRunner.execute();
@@ -1226,8 +1314,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override
public PageList<BundleVersion> findBundleVersionsByCriteria(Subject subject, BundleVersionCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- ;
-
CriteriaQueryRunner<BundleVersion> queryRunner = new CriteriaQueryRunner<BundleVersion>(criteria, generator,
entityManager);
return queryRunner.execute();
@@ -1236,8 +1322,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override
public PageList<BundleFile> findBundleFilesByCriteria(Subject subject, BundleFileCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- ;
-
CriteriaQueryRunner<BundleFile> queryRunner = new CriteriaQueryRunner<BundleFile>(criteria, generator,
entityManager);
return queryRunner.execute();
@@ -1246,8 +1330,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override
public PageList<Bundle> findBundlesByCriteria(Subject subject, BundleCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- ;
-
CriteriaQueryRunner<Bundle> queryRunner = new CriteriaQueryRunner<Bundle>(criteria, generator, entityManager);
return queryRunner.execute();
}
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 c917d80..3069739 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
@@ -19,6 +19,7 @@
package org.rhq.enterprise.server.bundle;
import java.util.HashMap;
+import java.util.Map;
import javax.ejb.Local;
@@ -186,4 +187,16 @@ public interface BundleManagerLocal extends BundleManagerRemote {
BundleResourceDeployment setBundleResourceDeploymentStatus(Subject subject, int resourceDeploymentId,
BundleDeploymentStatus status) throws Exception;
+ /**
+ * This is for internal use only - when {@link #purgeBundleDestination(Subject, int)} is done, it
+ * calls this so the purge can be finalized. This is required because this method is called with
+ * a transactional context, as opposed to the main purge method.
+ *
+ * @param subject
+ * @param bundleDeployment
+ * @param failedToPurge
+ * @throws Exception
+ */
+ void _finalizePurge(Subject subject, BundleDeployment bundleDeployment,
+ Map<BundleResourceDeployment, String> failedToPurge) throws Exception;
}
diff --git a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
index 4a51bb2..24b6b72 100644
--- a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
+++ b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
@@ -140,6 +140,7 @@ public class AntBundlePluginComponent implements ResourceComponent, BundleFacet
// Send the diffs to the Server so it can store them as an entry in the deployment history.
BundleManagerProvider bundleManagerProvider = request.getBundleManagerProvider();
DeployDifferences diffs = project.getDeployDifferences();
+ // TODO: put the diffs in the "attachment" area and make it more formatted/legible
bundleManagerProvider.auditDeployment(resourceDeployment, "Deployment Differences", project.getName(),
BundleResourceDeploymentHistory.Category.DEPLOY_STEP, null, diffs.toString(), null);
} catch (Throwable t) {
commit 5e1bc40e55ea854d21833b5cba82bfd82f4964d6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Jan 13 12:39:49 2011 -0500
fix the delete bundle confirmation messages
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 96ffd49..f4801ea 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
@@ -231,7 +231,7 @@ public class BundleView extends LocatableVLayout implements BookmarkableView {
deleteButton.setIcon("subsystems/bundle/BundleAction_Delete_16.png");
deleteButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
- SC.ask(MSG.view_bundle_list_deleteConfirm(), new BooleanCallback() {
+ SC.ask(MSG.view_bundle_deleteConfirm(), new BooleanCallback() {
public void execute(Boolean aBoolean) {
if (aBoolean) {
bundleManager.deleteBundle(bundleBeingViewed, new AsyncCallback<Void>() {
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 643d13a..ceb3c30 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
@@ -139,7 +139,7 @@ public class BundlesListView extends Table<RPCDataSource<BundleWithLatestVersion
}
});
- addTableAction(extendLocatorId("Delete"), MSG.common_button_delete(), MSG.common_msg_areYouSure(),
+ addTableAction(extendLocatorId("Delete"), 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) {
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 6ca3f92..4322960 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
@@ -907,6 +907,7 @@ view_bundle_recipe = Recipe
view_bundle_revert = Revert
view_bundle_purge = Purge
view_bundle_versions = Versions
+view_bundle_deleteConfirm = Are you sure you want to delete this bundle? All versions, destinations and deployments for this bundle will also be deleted.
# individual bundle views/wizards
view_bundle_fileListView_fileSize = File Size
commit b8a69d8b97c64c98e61da530b25be2ea369d0fd2
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Jan 13 10:11:05 2011 -0500
BZ 645412 the start of the end-to-end impl of purging bundles from remote platforms
This isn't fully functional yet - there is a main TODO in SLSB BundleManager:
// TODO loop through each deployment and purge it on agent
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundleAgentService.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundleAgentService.java
index 345567f..29e4e47 100644
--- a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundleAgentService.java
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundleAgentService.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2010 Red Hat, Inc.
+ * Copyright (C) 2005-2011 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -36,4 +36,11 @@ public interface BundleAgentService {
* @return the results of the immediate scheduling
*/
BundleScheduleResponse schedule(BundleScheduleRequest request);
+
+ /**
+ * Purges the live deployment off the local filesystem.
+ * @param request
+ * @return the results of the purge
+ */
+ BundlePurgeResponse purge(BundlePurgeRequest request);
}
\ No newline at end of file
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeRequest.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeRequest.java
new file mode 100644
index 0000000..e1d83f2
--- /dev/null
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeRequest.java
@@ -0,0 +1,57 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.rhq.core.clientapi.agent.bundle;
+
+import java.io.Serializable;
+
+import org.rhq.core.domain.bundle.BundleResourceDeployment;
+
+/**
+ * The request that the server sends down to the agent to purge the live bundle deployment.
+ *
+ * @author John Mazzitelli
+ */
+public class BundlePurgeRequest implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private BundleResourceDeployment resourceDeployment;
+
+ public BundlePurgeRequest(BundleResourceDeployment resourceDeployment) {
+ this.resourceDeployment = resourceDeployment;
+ }
+
+ /**
+ * @return the live resource deployment that is to be purged
+ */
+ public BundleResourceDeployment getLiveBundleResourceDeployment() {
+ return resourceDeployment;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder(this.getClass() + ": ");
+ str.append("live-deployment=[").append(resourceDeployment.toString()).append("]");
+ return str.toString();
+ }
+}
diff --git a/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeResponse.java b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeResponse.java
new file mode 100644
index 0000000..53db77c
--- /dev/null
+++ b/modules/core/client-api/src/main/java/org/rhq/core/clientapi/agent/bundle/BundlePurgeResponse.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.rhq.core.clientapi.agent.bundle;import java.io.Serializable;
+
+import org.rhq.core.util.exception.ThrowableUtil;
+;
+
+/**
+ * The results of the purge.
+ *
+ * @author John Mazzitelli
+ */
+public class BundlePurgeResponse implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private String errorMessage;
+
+ public BundlePurgeResponse() {
+ }
+
+ public boolean isSuccess() {
+ return this.errorMessage == null;
+ }
+
+ public String getErrorMessage() {
+ return this.errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public void setErrorMessage(Throwable t) {
+ this.errorMessage = ThrowableUtil.getAllMessages(t);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder(this.getClass().getSimpleName());
+ if (getErrorMessage() != null) {
+ str.append(" error=[").append(getErrorMessage()).append("];");
+ }
+ str.append(" success=[").append(isSuccess()).append("]");
+ return str.toString();
+ }
+}
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundleFacet.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundleFacet.java
index 2b76c0c..592e63f 100644
--- a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundleFacet.java
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundleFacet.java
@@ -29,4 +29,6 @@ package org.rhq.core.pluginapi.bundle;
*/
public interface BundleFacet {
BundleDeployResult deployBundle(BundleDeployRequest request);
+
+ BundlePurgeResult purgeBundle(BundlePurgeRequest request);
}
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeRequest.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeRequest.java
new file mode 100644
index 0000000..6f41339
--- /dev/null
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeRequest.java
@@ -0,0 +1,67 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2010 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.pluginapi.bundle;
+
+import java.io.Serializable;
+
+import org.rhq.core.domain.bundle.BundleResourceDeployment;
+
+/**
+ * A request to purge a bundle, essentially erasing the bundle files from the destination.
+ *
+ * @author John Mazzitelli
+ */
+public class BundlePurgeRequest implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private BundleResourceDeployment resourceDeployment;
+ private BundleManagerProvider bundleManagerProvider;
+
+ public BundlePurgeRequest() {
+ }
+
+ /**
+ * This is information about the last known live resource deployment - this is to be purged.
+ *
+ * @return information about the live resource deployment that is to be purged
+ */
+ public BundleResourceDeployment getLiveResourceDeployment() {
+ return resourceDeployment;
+ }
+
+ public void setLiveResourceDeployment(BundleResourceDeployment resourceDeployment) {
+ this.resourceDeployment = resourceDeployment;
+ }
+
+ public BundleManagerProvider getBundleManagerProvider() {
+ return this.bundleManagerProvider;
+ }
+
+ public void setBundleManagerProvider(BundleManagerProvider provider) {
+ this.bundleManagerProvider = provider;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder(this.getClass() + ": ");
+ str.append("live-deployment-to-be-purge=[").append(resourceDeployment.toString()).append("], ");
+ return str.toString();
+ }
+}
diff --git a/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeResult.java b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeResult.java
new file mode 100644
index 0000000..71e0dfb
--- /dev/null
+++ b/modules/core/plugin-api/src/main/java/org/rhq/core/pluginapi/bundle/BundlePurgeResult.java
@@ -0,0 +1,65 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2011 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.core.pluginapi.bundle;
+
+import java.io.Serializable;
+
+import org.rhq.core.util.exception.ThrowableUtil;
+
+/**
+ * The results after an attempt to purge a bundle has been completed.
+ *
+ * @author John Mazzitelli
+ */
+public class BundlePurgeResult implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private String errorMessage;
+
+ public boolean isSuccess() {
+ return this.errorMessage == null;
+ }
+
+ public String getErrorMessage() {
+ return this.errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public void setErrorMessage(Throwable t) {
+ this.errorMessage = ThrowableUtil.getAllMessages(t);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder(this.getClass().getSimpleName());
+ if (getErrorMessage() != null) {
+ str.append(" error=[").append(getErrorMessage()).append("];");
+ }
+ str.append(" success=[").append(isSuccess()).append("]");
+ return str.toString();
+ }
+
+}
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java
index 8f1525b..b945ff1 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/bundle/BundleManager.java
@@ -37,6 +37,8 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.bundle.BundleAgentService;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeRequest;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeResponse;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleRequest;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleResponse;
import org.rhq.core.clientapi.server.bundle.BundleServerService;
@@ -46,6 +48,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.BundleResourceDeploymentHistory.Status;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
@@ -62,6 +65,7 @@ import org.rhq.core.pluginapi.bundle.BundleDeployRequest;
import org.rhq.core.pluginapi.bundle.BundleDeployResult;
import org.rhq.core.pluginapi.bundle.BundleFacet;
import org.rhq.core.pluginapi.bundle.BundleManagerProvider;
+import org.rhq.core.pluginapi.bundle.BundlePurgeResult;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
@@ -81,6 +85,9 @@ public class BundleManager extends AgentService implements BundleAgentService, B
private final String AUDIT_FILE_DOWNLOAD_ENDED = "File Download Started";
private final String AUDIT_FILE_DOWNLOAD_STARTED = "File Download Started";
+ private final String AUDIT_PURGE_STARTED = "Purge Started";
+ private final String AUDIT_PURGE_ENDED = "Purge Ended";
+
private PluginContainerConfiguration configuration;
private ExecutorService deployerThreadPool;
@@ -126,6 +133,7 @@ public class BundleManager extends AgentService implements BundleAgentService, B
return size;
}
+ @Override
public BundleScheduleResponse schedule(final BundleScheduleRequest request) {
final BundleScheduleResponse response = new BundleScheduleResponse();
@@ -207,6 +215,58 @@ public class BundleManager extends AgentService implements BundleAgentService, B
return response;
}
+ @Override
+ public BundlePurgeResponse purge(BundlePurgeRequest request) {
+ final BundlePurgeResponse response = new BundlePurgeResponse();
+
+ try {
+ final BundleResourceDeployment resourceDeployment = request.getLiveBundleResourceDeployment();
+ final BundleDeployment bundleDeployment = resourceDeployment.getBundleDeployment();
+
+ // find the resource that will purge the bundle
+ InventoryManager im = PluginContainer.getInstance().getInventoryManager();
+ BundleType bundleType = bundleDeployment.getBundleVersion().getBundle().getBundleType();
+ ResourceType resourceType = bundleType.getResourceType();
+ Set<Resource> resources = im.getResourcesWithType(resourceType);
+ if (resources.isEmpty()) {
+ throw new Exception("No bundle plugin supports bundle type [" + bundleType + "]");
+ }
+ final int bundleHandlerResourceId = resources.iterator().next().getId();
+ final ResourceContainer resourceContainer = im.getResourceContainer(bundleHandlerResourceId);
+ if (null == resourceContainer.getResourceContext()) {
+ throw new Exception("No bundle plugin resource available to handle purge for bundle type ["
+ + bundleType
+ + "]. Ensure the bundle plugin is deployed and its resource is imported into inventory.");
+ }
+
+ // purge the bundle utilizing the bundle facet object
+ String deploymentMessage = "Deployment [" + bundleDeployment + "] to be purged via ["
+ + resourceDeployment.getResource() + "]";
+ auditDeployment(resourceDeployment, AUDIT_PURGE_STARTED, bundleDeployment.getName(), deploymentMessage);
+
+ org.rhq.core.pluginapi.bundle.BundlePurgeRequest purgeRequest = new org.rhq.core.pluginapi.bundle.BundlePurgeRequest();
+ purgeRequest.setBundleManagerProvider(this);
+ purgeRequest.setLiveResourceDeployment(resourceDeployment);
+
+ // get the bundle facet object that will process the bundle and call it to start the purge
+ int facetMethodTimeout = 30 * 60 * 1000; // 30 minutes should be enough time for the bundle plugin to purge everything
+ BundleFacet bundlePluginComponent = getBundleFacet(bundleHandlerResourceId, facetMethodTimeout);
+ BundlePurgeResult result = bundlePluginComponent.purgeBundle(purgeRequest);
+ if (result.isSuccess()) {
+ auditDeployment(resourceDeployment, AUDIT_PURGE_ENDED, bundleDeployment.getName(), deploymentMessage);
+ } else {
+ response.setErrorMessage(result.getErrorMessage());
+ auditDeployment(resourceDeployment, AUDIT_PURGE_ENDED, bundleDeployment.getName(), null,
+ Status.FAILURE, "Failed: " + deploymentMessage, result.getErrorMessage());
+ }
+ } catch (Throwable t) {
+ log.error("Failed to purge bundle: " + request, t);
+ response.setErrorMessage(t);
+ }
+
+ return response;
+ }
+
/**
* convenience method:<br/>
* category defaults to null<br/>
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 324b510..d471742 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
@@ -189,11 +189,47 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
revertButton.setIcon("subsystems/bundle/BundleAction_Revert_16.png");
revertButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
- new BundleRevertWizard(destination).startWizard();
+ SC.ask(MSG.view_bundle_dest_revertConfirm(), new BooleanCallback() {
+ public void execute(Boolean aBoolean) {
+ if (aBoolean) {
+ new BundleRevertWizard(destination).startWizard();
+ }
+ }
+ });
}
});
actionLayout.addMember(revertButton);
+ IButton purgeButton = new LocatableIButton(actionLayout.extendLocatorId("Purge"), MSG.view_bundle_purge());
+ purgeButton.setIcon("subsystems/bundle/BundleDestinationAction_Purge_16.png");
+ purgeButton.addClickHandler(new ClickHandler() {
+ public void onClick(ClickEvent clickEvent) {
+ SC.ask(MSG.view_bundle_dest_purgeConfirm(), new BooleanCallback() {
+ public void execute(Boolean aBoolean) {
+ if (aBoolean) {
+ bundleService.purgeBundleDestination(destination.getId(), new AsyncCallback<Void>() {
+ @Override
+ public void onFailure(Throwable caught) {
+ CoreGUI.getErrorHandler().handleError(
+ MSG.view_bundle_dest_purgeFailure(destination.getName()), caught);
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ CoreGUI.getMessageCenter().notify(
+ new Message(MSG.view_bundle_dest_purgeSuccessful(destination.getName()),
+ Message.Severity.Info));
+ // Bundle destination is purged, go back to bundle destinations root view
+ CoreGUI.goToView(LinkManager.getBundleDestinationLink(bundle.getId(), 0));
+ }
+ });
+ }
+ }
+ });
+ }
+ });
+ actionLayout.addMember(purgeButton);
+
IButton deleteButton = new LocatableIButton(actionLayout.extendLocatorId("Delete"), MSG.common_button_delete());
deleteButton.setIcon("subsystems/bundle/BundleDestinationAction_Delete_16.png");
deleteButton.addClickHandler(new ClickHandler() {
@@ -212,7 +248,7 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
CoreGUI.getMessageCenter().notify(
new Message(MSG.view_bundle_dest_deleteSuccessful(destination.getName()),
Message.Severity.Info));
- // Bundle destination is deleted, go back to main bundle view
+ // Bundle destination is deleted, go back to bundle destinations root view
CoreGUI.goToView(LinkManager.getBundleDestinationLink(bundle.getId(), 0), true);
}
});
@@ -226,6 +262,7 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
if (!canManageBundles) {
deployButton.setDisabled(true);
revertButton.setDisabled(true);
+ purgeButton.setDisabled(true);
deleteButton.setDisabled(true);
}
@@ -264,4 +301,4 @@ public class BundleDestinationView extends LocatableVLayout implements Bookmarka
});
}
-}
\ No newline at end of file
+}
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 4c7b209..79166ba 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
@@ -96,4 +96,5 @@ public interface BundleGWTService extends RemoteService {
BundleDeployment scheduleRevertBundleDeployment(int bundleDestinationId, String deploymentDescription,
boolean isCleanDeployment) throws RuntimeException;
+ void purgeBundleDestination(int bundleDestinationId) throws RuntimeException;
}
\ No newline at end of file
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 4049454..daf457d 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
@@ -266,4 +266,12 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund
throw new RuntimeException(ThrowableUtil.getAllMessages(t));
}
}
+
+ public void purgeBundleDestination(int bundleDestinationId) throws RuntimeException {
+ try {
+ bundleManager.purgeBundleDestination(getSessionSubject(), bundleDestinationId);
+ } catch (Throwable t) {
+ throw new RuntimeException(ThrowableUtil.getAllMessages(t));
+ }
+ }
}
\ No newline at end of file
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 acfd5e2..6ca3f92 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
@@ -905,6 +905,7 @@ view_bundle_files = Files
view_bundle_latestVersion = Latest Version
view_bundle_recipe = Recipe
view_bundle_revert = Revert
+view_bundle_purge = Purge
view_bundle_versions = Versions
# individual bundle views/wizards
@@ -970,7 +971,11 @@ view_bundle_dest_loadFailureVersionInfo = Failed to load bundle destination depl
view_bundle_dest_backToBundle = Back to Bundle
view_bundle_dest_tagUpdateFailure = Failed to update bundle destination tags
view_bundle_dest_tagUpdateSuccessful = You have successfully updated the bundle destination tags
-view_bundle_dest_deleteConfirm = Are you sure you want to delete this bundle destination?
+view_bundle_dest_purgeConfirm = This will purge the bundle content from all remote machines. Are you sure you want to do this?
+view_bundle_dest_purgeFailure = Failed to purge the bundle destination [{0}] from some or all of the remote machines.
+view_bundle_dest_purgeSuccessful = You successfully purged the bundle destination [{0}] from all of the remote machines.
+view_bundle_dest_revertConfirm = This will revert all remote machines back to the previous bundle deployment. Are you sure you want to do this?
+view_bundle_dest_deleteConfirm = Are you sure you want to delete this bundle destination? This only deletes it from the database; all bundle content that was deployed to this destination on remote machines will remain.
view_bundle_dest_deleteFailure = Failed to delete the bundle destination [{0}]
view_bundle_dest_deleteSuccessful = You successfully deleted the bundle destination [{0}]
view_bundle_resDeployDS_loadFailure = Failed to load bundle resource deployments
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16.png b/modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16.png
new file mode 100644
index 0000000..c370e20
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16.png differ
diff --git a/modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16_Disabled.png b/modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16_Disabled.png
new file mode 100644
index 0000000..7647069
Binary files /dev/null and b/modules/enterprise/gui/coregui/src/main/webapp/images/subsystems/bundle/BundleDestinationAction_Purge_16_Disabled.png differ
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 25ff496..0f99049 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
@@ -142,6 +142,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@EJB
private ResourceGroupManagerLocal resourceGroupManager;
+ @Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleResourceDeploymentHistory addBundleResourceDeploymentHistory(Subject subject, int bundleDeploymentId,
@@ -159,6 +160,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return history;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public Bundle createBundle(Subject subject, String name, String description, int bundleTypeId) throws Exception {
if (null == name || "".equals(name.trim())) {
@@ -201,6 +203,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundle;
}
+ @Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleDeployment createBundleDeploymentInNewTrans(Subject subject, int bundleVersionId,
@@ -218,6 +221,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return createBundleDeploymentImpl(subject, bundleVersion, bundleDestination, name, description, configuration);
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleDeployment createBundleDeployment(Subject subject, int bundleVersionId, int bundleDestinationId,
String description, Configuration configuration) throws Exception {
@@ -262,6 +266,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return deployment;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleDestination createBundleDestination(Subject subject, int bundleId, String name, String description,
String deployDir, Integer groupId) throws Exception {
@@ -289,6 +294,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return dest;
}
+ @Override
public String getBundleDeploymentName(Subject subject, int bundleDestinationId, int bundleVersionId,
int prevDeploymentId) {
BundleDestination bundleDestination = entityManager.find(BundleDestination.class, bundleDestinationId);
@@ -367,6 +373,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return deploymentName;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleType createBundleType(Subject subject, String name, int resourceTypeId) throws Exception {
if (null == name || "".equals(name.trim())) {
@@ -383,6 +390,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundleType;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleVersion createBundleAndBundleVersion(Subject subject, String bundleName, String bundleDescription,
int bundleTypeId, String bundleVersionName, String bundleVersionDescription, String version, String recipe)
@@ -406,6 +414,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bv;
}
+ @Override
@SuppressWarnings("unchecked")
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleVersion createBundleVersion(Subject subject, int bundleId, String name, String description,
@@ -476,6 +485,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundleVersion;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleVersion createBundleVersionViaRecipe(Subject subject, String recipe) throws Exception {
@@ -486,6 +496,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundleVersion;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
@TransactionAttribute(TransactionAttributeType.NEVER)
public BundleVersion createBundleVersionViaFile(Subject subject, File distributionFile) throws Exception {
@@ -497,6 +508,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundleVersion;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
@TransactionAttribute(TransactionAttributeType.NEVER)
public BundleVersion createBundleVersionViaURL(Subject subject, String distributionFileUrl) throws Exception {
@@ -659,6 +671,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return newVersion;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleFile addBundleFile(Subject subject, int bundleVersionId, String name, String version,
Architecture architecture, InputStream fileStream) throws Exception {
@@ -716,6 +729,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundleFile;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleFile addBundleFileViaByteArray(Subject subject, int bundleVersionId, String name, String version,
Architecture architecture, byte[] fileBytes) throws Exception {
@@ -723,6 +737,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return addBundleFile(subject, bundleVersionId, name, version, architecture, new ByteArrayInputStream(fileBytes));
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleFile addBundleFileViaURL(Subject subject, int bundleVersionId, String name, String version,
Architecture architecture, String bundleFileUrl) throws Exception {
@@ -733,6 +748,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return addBundleFile(subject, bundleVersionId, name, version, architecture, url.openStream());
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleFile addBundleFileViaPackageVersion(Subject subject, int bundleVersionId, String name,
int packageVersionId) throws Exception {
@@ -760,12 +776,35 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return bundleFile;
}
+ @Override
+ @RequiredPermission(Permission.MANAGE_BUNDLE)
+ public void purgeBundleDestination(Subject subject, int bundleDestinationId) throws Exception {
+ BundleDeploymentCriteria c = new BundleDeploymentCriteria();
+ c.addFilterDestinationId(bundleDestinationId);
+ c.addFilterIsLive(true);
+ c.fetchBundleVersion(true);
+ c.fetchResourceDeployments(true);
+ c.fetchDestination(true);
+ List<BundleDeployment> liveDeployments = bundleManager.findBundleDeploymentsByCriteria(subject, c);
+ if (1 != liveDeployments.size()) {
+ throw new IllegalArgumentException("No live deployment to purge is found for destinationId ["
+ + bundleDestinationId + "]");
+ }
+ BundleDeployment liveDeployment = liveDeployments.get(0);
+ BundleDestination destination = liveDeployment.getDestination();
+ List<BundleResourceDeployment> resourceDeploys = liveDeployment.getResourceDeployments();
+
+ // TODO loop through each deployment and purge it on agent
+ }
+
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleDeployment scheduleBundleDeployment(Subject subject, int bundleDeploymentId, boolean isCleanDeployment)
throws Exception {
return scheduleBundleDeploymentImpl(subject, bundleDeploymentId, isCleanDeployment, false);
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleDeployment scheduleRevertBundleDeployment(Subject subject, int bundleDestinationId,
String deploymentDescription, boolean isCleanDeployment) throws Exception {
@@ -920,6 +959,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return resourceDeployment;
}
+ @Override
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleScheduleRequest getScheduleRequest(Subject subject, int resourceDeploymentId,
@@ -971,6 +1011,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return request;
}
+ @Override
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleResourceDeployment createBundleResourceDeployment(Subject subject, int bundleDeploymentId,
@@ -991,6 +1032,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return resourceDeployment;
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public BundleResourceDeployment setBundleResourceDeploymentStatus(Subject subject, int resourceDeploymentId,
BundleDeploymentStatus status) throws Exception {
@@ -1042,6 +1084,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
// return groupDeployment;
//}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public Set<String> getBundleVersionFilenames(Subject subject, int bundleVersionId, boolean withoutBundleFileOnly)
throws Exception {
@@ -1081,6 +1124,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public HashMap<String, Boolean> getAllBundleVersionFilenames(Subject subject, int bundleVersionId) throws Exception {
@@ -1114,6 +1158,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
}
+ @Override
@SuppressWarnings("unchecked")
public List<BundleType> getAllBundleTypes(Subject subject) {
// the list of types will be small, no need to support paging
@@ -1122,6 +1167,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return types;
}
+ @Override
public BundleType getBundleType(Subject subject, String bundleTypeName) {
// the list of types will be small, no need to support paging
Query q = entityManager.createNamedQuery(BundleType.QUERY_FIND_BY_NAME);
@@ -1130,6 +1176,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return type;
}
+ @Override
public PageList<BundleDeployment> findBundleDeploymentsByCriteria(Subject subject, BundleDeploymentCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
@@ -1140,6 +1187,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return queryRunner.execute();
}
+ @Override
public PageList<BundleDestination> findBundleDestinationsByCriteria(Subject subject,
BundleDestinationCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
@@ -1150,6 +1198,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return queryRunner.execute();
}
+ @Override
public PageList<BundleResourceDeployment> findBundleResourceDeploymentsByCriteria(Subject subject,
BundleResourceDeploymentCriteria criteria) {
@@ -1174,6 +1223,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return queryRunner.execute();
}
+ @Override
public PageList<BundleVersion> findBundleVersionsByCriteria(Subject subject, BundleVersionCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
;
@@ -1183,6 +1233,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return queryRunner.execute();
}
+ @Override
public PageList<BundleFile> findBundleFilesByCriteria(Subject subject, BundleFileCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
;
@@ -1192,6 +1243,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return queryRunner.execute();
}
+ @Override
public PageList<Bundle> findBundlesByCriteria(Subject subject, BundleCriteria criteria) {
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
;
@@ -1200,6 +1252,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return queryRunner.execute();
}
+ @Override
public PageList<BundleWithLatestVersionComposite> findBundlesWithLatestVersionCompositesByCriteria(Subject subject,
BundleCriteria criteria) {
@@ -1222,6 +1275,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
// to avoid deadlocks, you cannot delete multiple bundles concurrently (see BZ 606530)
// instead, this simple method just loops over the given array and deletes them serially
// note they all get deleted in their own transaction; this method is never in a tx itself
+ @Override
@TransactionAttribute(TransactionAttributeType.NEVER)
public void deleteBundles(Subject subject, int[] bundleIds) throws Exception {
if (bundleIds != null) {
@@ -1231,6 +1285,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
}
}
+ @Override
@SuppressWarnings("unchecked")
@RequiredPermission(Permission.MANAGE_BUNDLE)
public void deleteBundle(Subject subject, int bundleId) throws Exception {
@@ -1257,6 +1312,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
repoManager.deleteRepo(subjectManager.getOverlord(), bundleRepo.getId());
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public void deleteBundleDeployment(Subject subject, int bundleDeploymentId) throws Exception {
BundleDeployment doomed = this.entityManager.find(BundleDeployment.class, bundleDeploymentId);
@@ -1273,6 +1329,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
}
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public void deleteBundleDestination(Subject subject, int destinationId) throws Exception {
BundleDestination doomed = this.entityManager.find(BundleDestination.class, destinationId);
@@ -1292,6 +1349,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
entityManager.remove(doomed);
}
+ @Override
@RequiredPermission(Permission.MANAGE_BUNDLE)
public void deleteBundleVersion(Subject subject, int bundleVersionId, boolean deleteBundleIfEmpty) throws Exception {
BundleVersion bundleVersion = this.entityManager.find(BundleVersion.class, bundleVersionId);
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 e8fdd8f..231d4c3 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
@@ -330,6 +330,17 @@ public interface BundleManagerRemote {
*/
/**
+ * Purges the destination's live deployment content from the remote platforms.
+ *
+ * @param subject user that must have proper permissions
+ * @param bundleDestinationId the ID of the destination that is to be purged of bundle content
+ */
+ @WebMethod
+ void purgeBundleDestination( //
+ @WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "bundleDestinationId") int bundleDestinationId) throws Exception;
+
+ /**
* Deploy the bundle to the destination, as described in the provided deployment.
* Deployment is asynchronous so return of this method does not indicate individual resource deployments are
* complete. The returned BundleDeployment can be used to track the history of the individual deployments.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
index 484a751..056582f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java
@@ -374,6 +374,10 @@ public class WebservicesManagerBean implements WebservicesRemote {
isCleanDeployment);
}
+ public void purgeBundleDestination(Subject subject, int bundleDestinationId) throws Exception {
+ bundleManager.purgeBundleDestination(subject, bundleDestinationId);
+ }
+
//BUNDLEMANAGER: END ----------------------------------
//CALLTIMEDATAMANAGER: BEGIN ----------------------------------
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
index 2c08880..aa221f9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestAgentClient.java
@@ -25,6 +25,8 @@ import java.util.Set;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.bundle.BundleAgentService;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeRequest;
+import org.rhq.core.clientapi.agent.bundle.BundlePurgeResponse;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleRequest;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleResponse;
import org.rhq.core.clientapi.agent.configuration.ConfigurationAgentService;
@@ -55,7 +57,6 @@ import org.rhq.core.domain.discovery.AvailabilityReport;
import org.rhq.core.domain.discovery.MergeResourceResponse;
import org.rhq.core.domain.discovery.ResourceSyncInfo;
import org.rhq.core.domain.measurement.Availability;
-import org.rhq.core.domain.measurement.DataType;
import org.rhq.core.domain.measurement.MeasurementData;
import org.rhq.core.domain.measurement.MeasurementDataRequest;
import org.rhq.core.domain.measurement.ResourceMeasurementScheduleRequest;
@@ -75,201 +76,248 @@ public class TestAgentClient implements AgentClient, BundleAgentService, Content
this.commService = commService;
}
+ @Override
public Agent getAgent() {
return this.agent;
}
+ @Override
public BundleAgentService getBundleAgentService() {
return (commService.bundleService != null) ? commService.bundleService : this;
}
+ @Override
public ContentAgentService getContentAgentService() {
return (commService.contentService != null) ? commService.contentService : this;
}
+ @Override
public ResourceFactoryAgentService getResourceFactoryAgentService() {
return (commService.resourceFactoryService != null) ? commService.resourceFactoryService : this;
}
+ @Override
public ConfigurationAgentService getConfigurationAgentService() {
return (commService.configurationService != null) ? commService.configurationService : this;
}
+ @Override
public DiscoveryAgentService getDiscoveryAgentService() {
return (commService.discoveryService != null) ? commService.discoveryService : this;
}
+ @Override
public MeasurementAgentService getMeasurementAgentService() {
return (commService.measurementService != null) ? commService.measurementService : this;
}
+ @Override
public OperationAgentService getOperationAgentService() {
return (commService.operationService != null) ? commService.operationService : this;
}
+ @Override
public SupportAgentService getSupportAgentService() {
return (commService.supportService != null) ? commService.supportService : this;
}
+ @Override
public void startSending() {
return; // no-op
}
+ @Override
public void stopSending() {
return; // no-op
}
+ @Override
public boolean ping(long timeoutMillis) {
return true;
}
// provide no-ops for all agent services
-
+ @Override
public Set<MeasurementData> getRealTimeMeasurementValue(int resourceId, List<MeasurementDataRequest> requests) {
- return null; //To change body of implemented methods use File | Settings | File Templates.
+ return null;
}
+ @Override
public void scheduleCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
}
+ @Override
public void unscheduleCollection(Set<Integer> resourceIds) {
}
+ @Override
public void updateCollection(Set<ResourceMeasurementScheduleRequest> resourceSchedules) {
}
+ @Override
public Map<String, Object> getMeasurementScheduleInfoForResource(int resourceId) {
return null;
}
+ @Override
public ConfigurationUpdateResponse executeUpdateResourceConfigurationImmediately(ConfigurationUpdateRequest request)
throws PluginContainerException {
return null;
}
+ @Override
public Configuration loadResourceConfiguration(int resourceId) throws PluginContainerException {
return null;
}
- public Configuration loadResourceConfiguration(int resourceId, boolean fromStructured)
- throws PluginContainerException {
- return null;
- }
-
+ @Override
public Configuration merge(Configuration configuration, int resourceId, boolean fromStructured)
throws PluginContainerException {
return null;
}
+ @Override
public void updateResourceConfiguration(ConfigurationUpdateRequest request) {
}
+ @Override
public CancelResults cancelOperation(String jobId) {
return null;
}
+ @Override
public void invokeOperation(String jobId, int resourceId, String operationName, Configuration parameters)
throws PluginContainerException {
}
+ @Override
public void deletePackages(DeletePackagesRequest request) {
}
+ @Override
public void deployPackages(DeployPackagesRequest request) {
}
+ @Override
public ContentDiscoveryReport executeResourcePackageDiscoveryImmediately(int resourceId, String packageTypeName)
throws PluginContainerException {
return null;
}
+ @Override
public Set<ResourcePackageDetails> getLastDiscoveredResourcePackages(int resourceId) {
return null;
}
+ @Override
public void retrievePackageBits(RetrievePackageBitsRequest request) {
}
+ @Override
public List<DeployPackageStep> translateInstallationSteps(int resourceId, ResourcePackageDetails packageDetails)
throws PluginContainerException {
return null;
}
+ @Override
public void disableServiceScans(int serverResourceId) {
}
+ @Override
public void enableServiceScans(int serverResourceId, Configuration config) {
}
+ @Override
public AvailabilityReport executeAvailabilityScanImmediately(boolean changedOnlyReport) {
return null;
}
+ @Override
public InventoryReport executeServerScanImmediately() throws PluginContainerException {
return null;
}
+ @Override
public InventoryReport executeServiceScanImmediately() throws PluginContainerException {
return null;
}
+ @Override
public void executeServiceScanDeferred() {
return;
}
+ @Override
public Availability getCurrentAvailability(Resource resource) {
return null;
}
+ @Override
public Resource getPlatform() {
return null;
}
+ @Override
public MergeResourceResponse manuallyAddResource(ResourceType resourceType, int parentResourceId,
Configuration pluginConfiguration, int creatorSubjectId) throws InvalidPluginConfigurationClientException,
PluginContainerException {
return null;
}
+ @Override
public void uninventoryResource(int resourceId) {
}
+ @Override
public void updatePluginConfiguration(int resourceId, Configuration newPluginConfiguration)
throws InvalidPluginConfigurationClientException, PluginContainerException {
}
@Asynchronous(guaranteedDelivery = true)
+ @Override
public void synchronizeInventory(ResourceSyncInfo syncInfo) {
return;
}
+ @Override
public void createResource(CreateResourceRequest request) throws PluginContainerException {
}
+ @Override
public void deleteResource(DeleteResourceRequest request) throws PluginContainerException {
}
+ @Override
public CreateResourceResponse executeCreateResourceImmediately(CreateResourceRequest request)
throws PluginContainerException {
return null;
}
+ @Override
public DeleteResourceResponse executeDeleteResourceImmediately(DeleteResourceRequest request)
throws PluginContainerException {
return null;
}
+ @Override
public InputStream getSnapshotReport(int resourceId, String name, String description) throws Exception {
return null;
}
+ @Override
public Configuration validate(Configuration configuration, int resourceId, boolean isStructured)
throws PluginContainerException {
return null;
}
+ @Override
public BundleScheduleResponse schedule(BundleScheduleRequest request) {
return new BundleScheduleResponse();
}
+
+ @Override
+ public BundlePurgeResponse purge(BundlePurgeRequest request) {
+ return new BundlePurgeResponse();
+ }
}
diff --git a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
index 51098ea..4a51bb2 100644
--- a/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
+++ b/modules/plugins/ant-bundle/src/main/java/org/rhq/plugins/ant/AntBundlePluginComponent.java
@@ -43,6 +43,8 @@ import org.rhq.core.domain.bundle.BundleDeployment;
import org.rhq.core.domain.bundle.BundleResourceDeployment;
import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory;
import org.rhq.core.domain.bundle.BundleVersion;
+import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory.Category;
+import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory.Status;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertySimple;
@@ -51,9 +53,12 @@ import org.rhq.core.pluginapi.bundle.BundleDeployRequest;
import org.rhq.core.pluginapi.bundle.BundleDeployResult;
import org.rhq.core.pluginapi.bundle.BundleFacet;
import org.rhq.core.pluginapi.bundle.BundleManagerProvider;
+import org.rhq.core.pluginapi.bundle.BundlePurgeRequest;
+import org.rhq.core.pluginapi.bundle.BundlePurgeResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.core.system.SystemInfoFactory;
+import org.rhq.core.util.file.FileUtil;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.core.util.updater.DeployDifferences;
import org.rhq.core.util.updater.DeploymentsMetadata;
@@ -160,6 +165,38 @@ public class AntBundlePluginComponent implements ResourceComponent, BundleFacet
return result;
}
+ // TODO: this is copied from FileTemplate bundle plugin - I think we want to be more smart here since
+ // we have more metadata about the live deployment to be purged in our .rhqdeployments (specifically about
+ // the external raw files that we should delete)
+ public BundlePurgeResult purgeBundle(BundlePurgeRequest request) {
+ BundlePurgeResult result = new BundlePurgeResult();
+ try {
+ BundleResourceDeployment deploymentToPurge = request.getLiveResourceDeployment();
+ BundleDeployment bundleDeployment = deploymentToPurge.getBundleDeployment();
+ File deployDir = new File(bundleDeployment.getDestination().getDeployDir());
+ String deployDirAbsolutePath = deployDir.getAbsolutePath();
+ BundleManagerProvider bundleManagerProvider = request.getBundleManagerProvider();
+
+ // completely purge the deployment directory.
+ // TODO: if the receipe copied a file outside of the deployment directory, it will still exist. How do we remove those?
+ FileUtil.purge(deployDir, true);
+
+ if (!deployDir.exists()) {
+ bundleManagerProvider.auditDeployment(deploymentToPurge, "Purge",
+ "The destination directory has been purged", Category.AUDIT_MESSAGE, Status.SUCCESS,
+ "Directory purged: " + deployDirAbsolutePath, null);
+ } else {
+ bundleManagerProvider.auditDeployment(deploymentToPurge, "Purge",
+ "The destination directory failed to be purged", Category.AUDIT_MESSAGE, Status.FAILURE,
+ "The directory that failed to be purged: " + deployDirAbsolutePath, null);
+ }
+ } catch (Throwable t) {
+ log.error("Failed to purge bundle [" + request + "]", t);
+ result.setErrorMessage(t);
+ }
+ return result;
+ }
+
private BundleAntProject executeDeploymentPhase(File recipeFile, Properties antProps,
List<BuildListener> buildListeners, DeploymentPhase phase) throws InvalidBuildFileException {
AntLauncher antLauncher = new AntLauncher();
diff --git a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
index 0b96612..940a01e 100644
--- a/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
+++ b/modules/plugins/filetemplate-bundle/src/main/java/org/rhq/plugins/filetemplate/FileTemplateBundlePluginServerComponent.java
@@ -27,14 +27,19 @@ import org.rhq.bundle.filetemplate.recipe.RecipeParser;
import org.rhq.core.domain.bundle.BundleDeployment;
import org.rhq.core.domain.bundle.BundleResourceDeployment;
import org.rhq.core.domain.bundle.BundleVersion;
+import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory.Category;
+import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory.Status;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.pluginapi.bundle.BundleDeployRequest;
import org.rhq.core.pluginapi.bundle.BundleDeployResult;
import org.rhq.core.pluginapi.bundle.BundleFacet;
import org.rhq.core.pluginapi.bundle.BundleManagerProvider;
+import org.rhq.core.pluginapi.bundle.BundlePurgeRequest;
+import org.rhq.core.pluginapi.bundle.BundlePurgeResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.core.pluginapi.util.FileUtils;
+import org.rhq.core.util.file.FileUtil;
/**
* @author John Mazzitelli
@@ -120,4 +125,33 @@ public class FileTemplateBundlePluginServerComponent implements ResourceComponen
return result;
}
+
+ public BundlePurgeResult purgeBundle(BundlePurgeRequest request) {
+ BundlePurgeResult result = new BundlePurgeResult();
+ try {
+ BundleResourceDeployment deploymentToPurge = request.getLiveResourceDeployment();
+ BundleDeployment bundleDeployment = deploymentToPurge.getBundleDeployment();
+ File deployDir = new File(bundleDeployment.getDestination().getDeployDir());
+ String deployDirAbsolutePath = deployDir.getAbsolutePath();
+ BundleManagerProvider bundleManagerProvider = request.getBundleManagerProvider();
+
+ // completely purge the deployment directory.
+ // TODO: if the receipe copied a file outside of the deployment directory, it will still exist. How do we remove those?
+ FileUtil.purge(deployDir, true);
+
+ if (!deployDir.exists()) {
+ bundleManagerProvider.auditDeployment(deploymentToPurge, "Purge",
+ "The destination directory has been purged", Category.AUDIT_MESSAGE, Status.SUCCESS,
+ "Directory purged: " + deployDirAbsolutePath, null);
+ } else {
+ bundleManagerProvider.auditDeployment(deploymentToPurge, "Purge",
+ "The destination directory failed to be purged", Category.AUDIT_MESSAGE, Status.FAILURE,
+ "The directory that failed to be purged: " + deployDirAbsolutePath, null);
+ }
+ } catch (Throwable t) {
+ log.error("Failed to purge bundle [" + request + "]", t);
+ result.setErrorMessage(t);
+ }
+ return result;
+ }
}