/* * RHQ Management Platform * Copyright (C) 2005-2013 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.enterprise.server.content; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import java.util.Map; import java.util.Set; import javax.ejb.Local; import org.rhq.core.clientapi.server.content.ContentDiscoveryReport; import org.rhq.core.clientapi.server.content.ContentServiceResponse; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.content.Architecture; import org.rhq.core.domain.content.ContentServiceRequest; import org.rhq.core.domain.content.InstalledPackage; import org.rhq.core.domain.content.Package; import org.rhq.core.domain.content.PackageBits; import org.rhq.core.domain.content.PackageDetailsKey; import org.rhq.core.domain.content.PackageType; import org.rhq.core.domain.content.PackageVersion; import org.rhq.core.domain.content.transfer.DeployPackageStep; import org.rhq.core.domain.content.transfer.DeployPackagesResponse; import org.rhq.core.domain.content.transfer.RemovePackagesResponse; import org.rhq.core.domain.content.transfer.ResourcePackageDetails; import org.rhq.core.domain.resource.Resource; /** * EJB interface to the server content subsystem. * * @author Jason Dobies */ @Local public interface ContentManagerLocal extends ContentManagerRemote { // Use case logic -------------------------------------------- /** * This is currently ignored as the file size is computed * upon persist. */ public static final String UPLOAD_FILE_SIZE = "fileSize"; public static final String UPLOAD_FILE_INSTALL_DATE = "fileInstallDate"; /** * This doesn't seem to serve any purpose. */ public static final String UPLOAD_OWNER = "owner"; public static final String UPLOAD_FILE_NAME = "fileName"; public static final String UPLOAD_MD5 = "md5"; public static final String UPLOAD_DISPLAY_VERSION = "displayVersion"; /** * This is currently ignored as the SHA is computed upon * persist. */ public static final String UPLOAD_SHA256 = "sha256"; /** * Deploys a package on the specified resource. Each installed package entry should be populated with the <code> * PackageVersion</code> being installed, along with the deployment configuration values if any. This method will * take care of populating the rest of the values in each installed package object. * * @param user the user who is requesting the creation * @param resourceId identifies the resource against which the package will be deployed * @param packages packages (with their deployment time configuration values) to deploy * @param requestNotes user-specified notes on what is contained in this request */ void deployPackages(Subject user, int resourceId, Set<ResourcePackageDetails> packages, String requestNotes); /** * Deletes the specified package from the resource. * * @param user the user who is requesting the delete * @param resourceIds identifies the resources from which the packages should be deleted * @param installedPackageIds identifies all of the packages to be deleted */ void deletePackages(Subject user, int[] resourceIds, int[] installedPackageIds); /** * Requests the plugin load and send the actual bits for the specified package. * * @param user the user who is requesting the update * @param resourceId identifies the resource against which the package exists * @param installedPackageId id of the installed package to retrieve bits */ void retrieveBitsFromResource(Subject user, int resourceId, int installedPackageId); /** * Requests the plugin translate the installation steps of the specified package. * * @param resourceId resource against which the package is being installed * @param packageDetails package being installed * @return list of deployment steps if the plugin specified them; <code>null</code> if they cannot be determined * for this package * @throws Exception if there is an error either contacting the agent or in the plugin's generation of the steps */ List<DeployPackageStep> translateInstallationSteps(int resourceId, ResourcePackageDetails packageDetails) throws Exception; // The methods below should not be exposed to remote clients // Calls from the agent -------------------------------------------- /** * For documentation, see * {@link org.rhq.core.clientapi.server.content.ContentServerService#mergeDiscoveredPackages(org.rhq.core.clientapi.server.content.ContentDiscoveryReport)} * . */ void mergeDiscoveredPackages(ContentDiscoveryReport report); /** * For documentation, see * {@link org.rhq.core.clientapi.server.content.ContentServerService#completeDeployPackageRequest(org.rhq.core.domain.content.transfer.DeployPackagesResponse)} * . */ void completeDeployPackageRequest(DeployPackagesResponse response); /** * For documentation, see * {@link org.rhq.core.clientapi.server.content.ContentServerService#completeDeletePackageRequest(org.rhq.core.domain.content.transfer.RemovePackagesResponse)} * . */ void completeDeletePackageRequest(RemovePackagesResponse response); /** * For documentation, see * {@link org.rhq.core.clientapi.server.content.ContentServerService#completeRetrievePackageBitsRequest(org.rhq.core.clientapi.server.content.ContentServiceResponse, java.io.InputStream)} * )}. */ void completeRetrievePackageBitsRequest(ContentServiceResponse response, InputStream bitStream); /** * For documentation, see * {@link org.rhq.core.clientapi.server.content.ContentServerService#loadDependencies(int, java.util.Set)} */ Set<ResourcePackageDetails> loadDependencies(int requestId, Set<PackageDetailsKey> keys); // Internal Utilities -------------------------------------------- /** * For internal use only - Adds a request entry to the database to track the deployment of a group of packages. This * will be performed in a new transaction. * * @param resourceId resource against which the package request was executed * @param username user who made the request * @param packages packages being deployed in the request * @param requestNotes user-specified notes on what the request entails * * @return request entity after being persisted to the database (it's ID will be populated) */ ContentServiceRequest createDeployRequest(int resourceId, String username, Set<ResourcePackageDetails> packages, String requestNotes); /** * For internal use only - Adds a request entry to the database to track the deleting of currently installed * packages from the resource. This will be performed in a new transaction. * * @param resourceId resource against which the package request was executed * @param username user who made the request * @param installedPackageIds identifies the installed packages that are to be deleted; ids in this list must be of * valid <code>InstalledPackage</code> objects on the resource * @param requestNotes user-specified notes on what the request entails * * @return request entity after being persisted to the database (it's ID will be populated) */ ContentServiceRequest createRemoveRequest(int resourceId, String username, int[] installedPackageIds, String requestNotes); /** * For internal use only - Adds a request entry to the database to track the request for a package's bits. This will * be performed in a new transaction. * * @param resourceId resource against which the package request was executed * @param username user who made the request * @param installedPackageId package whose bits are being retrieved by the request; this must be the ID of a valid * <code>InstalledPackage</code> on the resource. * * @return request entity after being persisted to the database (it's ID will be populated) */ ContentServiceRequest createRetrieveBitsRequest(int resourceId, String username, int installedPackageId); /** * For internal use only - Updates a persisted <code>ContentServiceRequest</code> in the case a failure is * encountered during one of the use case methods (i.e. create, delete). * * @param requestId identifies the previously persisted request * @param error error encountered to cause the failure */ void failRequest(int requestId, Throwable error); /** * For internal use only - Will check to see if any in progress content request jobs are taking too long to finish * and if so marks them as failed. This method will be periodically called by the Server. * * @param subject only the overlord may execute this system operation */ void checkForTimedOutRequests(Subject subject); /** * Creates a new package version in the system. If the parent package (identified by the packageName parameter) does * not exist, it will be created. If a package version exists with the specified version ID, a new one will not be * created and the existing package version instance will be returned. * * @param subject the user requesting the package creation * @param packageName parent package name; uniquely identifies the package under which this version goes * @param packageTypeId identifies the type of package in case the general package needs to be created * @param version identifies the version to be create * @param displayVersion package display version * @param architectureId architecture of the newly created package version * * @return newly created package version if one did not exist; existing package version that matches these data if * one was found */ PackageVersion createPackageVersionWithDisplayVersion(Subject subject, String packageName, int packageTypeId, String version, String displayVersion, int architectureId, InputStream packageBitStream); /** * This method is essentially the same as {@link #createPackageVersion(Subject, String, int, String, int, InputStream)} * but will update the package bits if a package version with the provided identification already exists. * * @param subject the current user * @param packageName the name of the package (the general package will be created if none exists) * @param packageTypeId the id of the package type. This is ignored if the <code>newResourceTypeId</code> is not null * @param version the version of the package version being created * @param architectureId the architecture of the package version * @param packageBitStream the input stream with the package bits * @param packageUploadDetails additional details about the package. See the constants defined in this interface * @param repoId an optional id of the repo to insert the package version in * @return the newly create package version */ PackageVersion getUploadedPackageVersion(Subject subject, String packageName, int packageTypeId, String version, int architectureId, InputStream packageBitStream, Map<String, String> packageUploadDetails, Integer repoId); /** * Very simple method that persists the given package version within its own transaction. * * <p>This method is here to support {@link #persistOrMergePackageVersionSafely(PackageVersion)}, * it is not meant for general consumption.</p> * * @param pv the package version to persist * * @return the newly persisted package version */ PackageVersion persistPackageVersion(PackageVersion pv); /** * Finds, and if it doesn't exist, persists the package version. * If it already exists, it will return the merge the given PV with the object it found and return * the merged PV. * This performs its tasks safely; that is, it makes sure that no contraint violations occur * if the package version already exists. * * <p>This method is for a very specific use case - that is, when creating a package version * in a place where, concurrently, someone else might try to create the same package version. * It is not for general persisting/merging of package versions.</p> * * @param pv the package version to find and possibly persist to the database * * @return the package version that was found/persisted */ PackageVersion persistOrMergePackageVersionSafely(PackageVersion pv); /** * Very simple method that pesists the given package within its own transaction. * * <p>This method is here to support {@link #persistOrMergePackageSafely(Package)}, * it is not meant for general consumption.</p> * * @param pkg the package to persist * * @return the newly persisted package */ Package persistPackage(Package pkg); /** * Finds, and if it doesn't exist, persists the package. * If it already exists, it will return the merge the given package with the object it found and return * the merged package. * This performs its tasks safely; that is, it makes sure that no contraint violations occur * if the package already exists. * * <p>This method is for a very specific use case - that is, when creating a package * in a place where, concurrently, someone else might try to create the same package. * It is not for general persisting/merging of packages.</p> * * @param pkg the package to find and possibly persist to the database * * @return the package that was found/persisted */ Package persistOrMergePackageSafely(Package pkg); /** * Returns the entity associated with no architecture. * * @return no architecture entity */ Architecture getNoArchitecture(); /** * Returns list of version strings for installed packages on the resource. * @param subject * @param resourceId * @return List of InstalledPackage versions */ List<String> findInstalledPackageVersions(Subject subject, int resourceId); /** * Returns the package type that backs resources of the specified type. * * @param resourceTypeId identifies the resource type. * @return backing package type if one exists; <code>null</code> otherwise */ PackageType getResourceCreationPackageType(int resourceTypeId); /** * This method is used to persist new package types that are defined on the server-side * by some kind of plugin. * <p> * Server-side package types are used to identify data stored in the content subsystem * which don't have any agent-side counter-part. Such package types are required to have * the {@link PackageType#getResourceType() resource type} set to null. * * @param packageType the package type to persist * @return the persisted package type * @throws IllegalArgumentException if the supplied package type has non-null resource type */ PackageType persistServersidePackageType(PackageType packageType); void writeBlobOutToStream(OutputStream stream, PackageBits bits, boolean closeStreams); void updateBlobStream(InputStream stream, PackageBits bits, Map<String, String> contentDetails); /** * Get the file denoted by this <code>temporaryContentHandle</code>. * * @see org.rhq.enterprise.server.content.ContentManagerRemote#createTemporaryContentHandle() * @param temporaryContentHandle * @return the file denoted by this <code>temporaryContentHandle</code> */ File getTemporaryContentFile(String temporaryContentHandle); // used solely for Tx demarcation void handleDiscoveredPackage(Resource resource, ResourcePackageDetails discoveredPackage, Set<InstalledPackage> doomedPackages, long timestamp); // used solely for Tx demarcation void removeInstalledPackages(Resource resource, Set<InstalledPackage> doomedPackages, long timestamp); // used solely for Tx demarcation List<Integer> purgePackageBits(int packageId); // used solely for Tx demarcation void unlinkBlob(Integer bitId); void removeOrphanedPackageBits(); void removeHistoryDeploymentsBits(); }