private void audit(String action, BundleResourceDeploymentHistory.Status status, String message) { try { bundleManagerProvider.auditDeployment( bundleResourceDeployment, action, "recipe", null, status, message, null); if (log.isDebugEnabled()) { log.debug( "Deployment [" + bundleResourceDeployment.getBundleDeployment().getBundleVersion() + "] audit: action=[" + action + "], status=[" + status + "], message: " + message); } } catch (Exception e) { log.warn( "Failed to send audit message for deployment of [" + bundleResourceDeployment.getBundleDeployment().getBundleVersion() + "]. audit action=[" + action + "], status=[" + status + "], message: " + message); } }
private void completeDeployment( BundleResourceDeployment resourceDeployment, BundleDeploymentStatus status, String message) { getBundleServerService().setBundleDeploymentStatus(resourceDeployment.getId(), status); BundleResourceDeploymentHistory.Status auditStatus = BundleDeploymentStatus.SUCCESS.equals(status) ? BundleResourceDeploymentHistory.Status.SUCCESS : BundleResourceDeploymentHistory.Status.FAILURE; auditDeployment( resourceDeployment, AUDIT_DEPLOYMENT_ENDED, resourceDeployment.getBundleDeployment().getName(), null, auditStatus, message, null); }
public void auditDeployment( BundleResourceDeployment bundleResourceDeployment, String action, String info, BundleResourceDeploymentHistory.Category category, BundleResourceDeploymentHistory.Status status, String message, String attachment) { if (null == action || null == info) { throw new IllegalArgumentException("action or info is null"); } if (null == status) { status = BundleResourceDeploymentHistory.Status.SUCCESS; } BundleResourceDeploymentHistory history = new BundleResourceDeploymentHistory( "Bundle Plugin", action, info, category, status, message, attachment); log.debug("Reporting deployment step [" + history + "] to Server..."); getBundleServerService().addDeploymentHistory(bundleResourceDeployment.getId(), history); }
/** * Given a deployment, this examines the destination and the resource to determine where exactly * the bundle distribution should be written. * * @param bundleResourceDeployment describes where the bundle should be or is deployed * @return absolute directory location where the bundle should be deployed */ private File getAbsoluteDestinationDir(BundleResourceDeployment bundleResourceDeployment) { BundleDestination dest = bundleResourceDeployment.getBundleDeployment().getDestination(); String destBaseDirName = dest.getDestinationBaseDirectoryName(); String relativeDeployDir = dest.getDeployDir(); // paranoia, if no deploy dir is given, as assume it will be directly under the base location if (relativeDeployDir == null || relativeDeployDir.trim().length() == 0) { relativeDeployDir = File.separator; } // get the resource entity stored in our local inventory InventoryManager im = getInventoryManager(); Resource resource = bundleResourceDeployment.getResource(); ResourceContainer container = im.getResourceContainer(resource); resource = container.getResource(); // find out the type of base location that is specified by the bundle destination BundleDestinationBaseDirectory bundleDestBaseDir = null; ResourceTypeBundleConfiguration rtbc = resource.getResourceType().getResourceTypeBundleConfiguration(); if (rtbc == null) { throw new IllegalArgumentException( "The resource type doesn't support bundle deployments: " + resource); } for (BundleDestinationBaseDirectory bdbd : rtbc.getBundleDestinationBaseDirectories()) { if (bdbd.getName().equals(destBaseDirName)) { bundleDestBaseDir = bdbd; break; } } if (bundleDestBaseDir == null) { throw new IllegalArgumentException( "The resource type doesn't support bundle destination base location named [" + destBaseDirName + "]"); } // based on the type of destination base location, determine the root base directory String destBaseDirValueName = bundleDestBaseDir.getValueName(); // the name we look up in the given context String baseLocation; switch (bundleDestBaseDir.getValueContext()) { case fileSystem: { if (!new File(relativeDeployDir).isAbsolute()) { // the deploy dir is not absolute; since we need to pin it to something, we assume the // top root directory // unless the descriptor told us to go somewhere else differently baseLocation = destBaseDirValueName; // ultimately this came from the plugin descriptor if (baseLocation == null || baseLocation.trim().length() == 0) { baseLocation = File .separator; // paranoia, if the plugin descriptor didn't specify, assume the // top root directory } } else { baseLocation = null; // so the relativeDeployDir is processed as an absolute dir } break; } case pluginConfiguration: { baseLocation = resource.getPluginConfiguration().getSimpleValue(destBaseDirValueName, null); if (baseLocation == null) { throw new IllegalArgumentException( "Cannot determine the bundle base deployment location - " + "there is no plugin configuration setting for [" + destBaseDirValueName + "]"); } break; } case resourceConfiguration: { baseLocation = resource.getResourceConfiguration().getSimpleValue(destBaseDirValueName, null); if (baseLocation == null) { throw new IllegalArgumentException( "Cannot determine the bundle base deployment location - " + "there is no resource configuration setting for [" + destBaseDirValueName + "]"); } break; } case measurementTrait: { baseLocation = getMeasurementManager().getTraitValue(container, destBaseDirValueName); if (baseLocation == null) { throw new IllegalArgumentException( "Cannot obtain trait [" + destBaseDirName + "] for resource [" + resource.getName() + "]"); } break; } default: { throw new IllegalArgumentException( "Unknown bundle destination location context: " + bundleDestBaseDir); } } File destDir = new File(baseLocation, relativeDeployDir); if (!destDir.isAbsolute()) { throw new IllegalArgumentException( "The base location path specified by [" + destBaseDirValueName + "] in the context [" + bundleDestBaseDir.getValueContext() + "] along with the destination directory of [" + relativeDeployDir + "] did not resolve to an absolute path [" + destDir.getPath() + "] so there is no way to know where to put the bundle."); } return destDir; }
/** * Downloads the bundle's files into the bundle plugin's tmp directory and returns that tmp * directory. * * @param resourceDeployment access to deployment information, including what bundle files need to * be downloaded * @param downloadDir location where the bundle files should be downloaded * @return map of the package versions to their files that were downloaded * @throws Exception */ private Map<PackageVersion, File> downloadBundleFiles( BundleResourceDeployment resourceDeployment, File downloadDir) throws Exception { BundleDeployment bundleDeployment = resourceDeployment.getBundleDeployment(); BundleVersion bundleVersion = bundleDeployment.getBundleVersion(); Map<PackageVersion, File> packageVersionFiles = new HashMap<PackageVersion, File>(); List<PackageVersion> packageVersions = getAllBundleVersionPackageVersions(bundleVersion); for (PackageVersion packageVersion : packageVersions) { File packageFile = new File(downloadDir, packageVersion.getFileName()); try { verifyHash(packageVersion, packageFile); } catch (Exception e) { // file either doesn't exist or it hash doesn't match, download a new copy packageFile.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(packageFile); try { auditDeployment( resourceDeployment, AUDIT_FILE_DOWNLOAD_STARTED, packageVersion.getDisplayName(), "Downloading [" + packageVersion + "]"); long size = getFileContent(packageVersion, fos); if (packageVersion.getFileSize() != null && size != packageVersion.getFileSize().longValue()) { String message = "Downloaded bundle file [" + packageVersion + "] but its size was [" + size + "] when it was expected to be [" + packageVersion.getFileSize() + "]."; log.warn(message); auditDeployment( resourceDeployment, AUDIT_FILE_DOWNLOAD_ENDED, packageVersion.getDisplayName(), null, BundleResourceDeploymentHistory.Status.WARN, message, null); } else { auditDeployment( resourceDeployment, AUDIT_FILE_DOWNLOAD_ENDED, packageVersion.getDisplayName(), "Download complete for [" + packageVersion + "]"); } } catch (Exception e2) { String message = "Failed to downloaded bundle file [" + packageVersion + "] " + e2; log.warn(message); auditDeployment( resourceDeployment, AUDIT_FILE_DOWNLOAD_ENDED, packageVersion.getDisplayName(), null, BundleResourceDeploymentHistory.Status.FAILURE, message, null); } finally { fos.close(); } // now try to verify it again, if this throws an exception, that is very bad and we need to // abort verifyHash(packageVersion, packageFile); } packageVersionFiles.put(packageVersion, packageFile); } return packageVersionFiles; }
@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 = 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); File absoluteDestDir = getAbsoluteDestinationDir(request.getLiveBundleResourceDeployment()); org.rhq.core.pluginapi.bundle.BundlePurgeRequest purgeRequest = new org.rhq.core.pluginapi.bundle.BundlePurgeRequest(); purgeRequest.setBundleManagerProvider(this); purgeRequest.setLiveResourceDeployment(resourceDeployment); purgeRequest.setAbsoluteDestinationDirectory(absoluteDestDir); // 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; }
@Override public BundleScheduleResponse schedule(final BundleScheduleRequest request) { final BundleScheduleResponse response = new BundleScheduleResponse(); try { final BundleResourceDeployment resourceDeployment = request.getBundleResourceDeployment(); final BundleDeployment bundleDeployment = resourceDeployment.getBundleDeployment(); // find the resource that will handle the bundle processing InventoryManager im = 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 deployment for bundle type [" + bundleType + "]. Ensure the bundle plugin is deployed and its resource is imported into inventory."); } auditDeployment( resourceDeployment, AUDIT_DEPLOYMENT_SCHEDULED, bundleDeployment.getName(), "Scheduled deployment time: " + request.getRequestedDeployTimeAsString()); Runnable deployerRunnable = new Runnable() { public void run() { try { // pull down the bundle files that the plugin will need in order to process the // bundle File pluginTmpDir = resourceContainer.getResourceContext().getTemporaryDirectory(); File bundleFilesDir = new File( pluginTmpDir, "bundle-versions/" + bundleDeployment.getBundleVersion().getId()); bundleFilesDir.mkdirs(); // clean up any old downloads we may have retrieved before. This helps clean out // our temp directory so we don't unnecessarily fill up our file system with // obsolete files removeOldDownloadedBundleFiles(bundleFilesDir); // now download the bundle files we need for the current deployment Map<PackageVersion, File> downloadedFiles = downloadBundleFiles(resourceDeployment, bundleFilesDir); // deploy the bundle utilizing the bundle facet object String deploymentMessage = "Deployment [" + bundleDeployment + "] to [" + resourceDeployment.getResource() + "]"; auditDeployment( resourceDeployment, AUDIT_DEPLOYMENT_STARTED, bundleDeployment.getName(), deploymentMessage); File absoluteDestDir = getAbsoluteDestinationDir(request.getBundleResourceDeployment()); BundleDeployRequest deployRequest = new BundleDeployRequest(); deployRequest.setBundleManagerProvider(BundleManager.this); deployRequest.setResourceDeployment(resourceDeployment); deployRequest.setBundleFilesLocation(bundleFilesDir); deployRequest.setPackageVersionFiles(downloadedFiles); deployRequest.setCleanDeployment(request.isCleanDeployment()); deployRequest.setRevert(request.isRevert()); deployRequest.setAbsoluteDestinationDirectory(absoluteDestDir); // get the bundle facet object that will process the bundle and call it to start the // deployment int facetMethodTimeout = 4 * 60 * 60 * 1000; // 4 hours is given to the bundle plugin to do its thing BundleFacet bundlePluginComponent = getBundleFacet(bundleHandlerResourceId, facetMethodTimeout); BundleDeployResult result = bundlePluginComponent.deployBundle(deployRequest); if (result.isSuccess()) { completeDeployment( resourceDeployment, BundleDeploymentStatus.SUCCESS, deploymentMessage); } else { completeDeployment( resourceDeployment, BundleDeploymentStatus.FAILURE, result.getErrorMessage()); } } catch (InterruptedException ie) { log.error("Failed to complete bundle deployment due to interrupt", ie); completeDeployment( resourceDeployment, BundleDeploymentStatus.FAILURE, "Deployment interrupted"); } catch (Throwable t) { log.error("Failed to complete bundle deployment", t); completeDeployment( resourceDeployment, BundleDeploymentStatus.FAILURE, "Deployment failed: " + ThrowableUtil.getAllMessages(t)); } } }; this.deployerThreadPool.execute(deployerRunnable); } catch (Throwable t) { log.error("Failed to schedule bundle request: " + request, t); response.setErrorMessage(t); } return response; }