/*
* RHQ Management Platform
* Copyright (C) 2005-2015 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.bundle;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import org.rhq.core.clientapi.agent.bundle.BundleScheduleRequest;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.bundle.Bundle;
import org.rhq.core.domain.bundle.BundleDeployment;
import org.rhq.core.domain.bundle.BundleDeploymentStatus;
import org.rhq.core.domain.bundle.BundleResourceDeployment;
import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory;
import org.rhq.core.domain.bundle.BundleType;
import org.rhq.core.domain.bundle.BundleVersion;
import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.resource.ResourceType;
/**
* Local interface to the manager responsible for creating and managing bundles.
*
* @author John Mazzitelli
* @author Jay Shaughnessy
*/
@Local
public interface BundleManagerLocal extends BundleManagerRemote {
// Methods in the Local are not exposed to the remote API. This is is typically due to:
// - used strictly for internal processing (like generating history records)
// - transactional reasons (like needing REQUIRES_NEW)
// - security reasons
// - used for testing only
// - legacy reasons
/**
* Internal use only
* </p>
* Called internally to add history when action is taken against a deployment. This executes
* in a New Transaction and supports deployBundle and Agent requests.
* </p>
* This method performs NO AUTHZ!
* </p>
* @param subject
* @param resourceDeploymentId id of the deployment appending the history record
* @param history
* @return the persisted history
*/
BundleResourceDeploymentHistory addBundleResourceDeploymentHistoryInNewTrans(Subject subject,
int resourceDeploymentId, BundleResourceDeploymentHistory history) throws Exception;
/**
* Used by the UI. Performs security checks.
*
* @param subject the caller
* @param resourceDeploymentId id of the deployment
*
* @return the list of audit entities, or an empty list if the caller is not authorized to view this deployment.
*/
List<BundleResourceDeploymentHistory> getBundleResourceDeploymentHistories(Subject subject, int resourceDeploymentId);
/**
* Internal use only, and test entry point.
* <pre>
* Required Permissions (same as createInitialBundleVersionXxx): Either:
* - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES
* - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG
* - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG
* </pre>
* @param subject user that must have proper permissions
* @param name not null or empty
* @param description optional long description of the bundle
* @param bundleTypeId valid bundleType
* @param bundleGroupIds existing bundle groups for initial bundle assignment, null or 0 length for unassigned
* @return the persisted Bundle (id is assigned)
*/
Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int[] bundleGroupIds)
throws Exception;
/**
* Internal use only and test entry point.
*
* Convenience method that combines {@link #createBundle(Subject, String, int)} and {@link #createBundleVersion(Subject, int, String, String, String)}.
* This will first check to see if a bundle with the given type/name exists - if it doesn't, it will be created. If it does, it will be reused.
* This will then create the bundle version that will be associated with the bundle that was created or found.
* <pre>
* Required Permissions (same as createInitialBundleVersionXxx): Either:
* - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES
* - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG
* - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG
* </pre>
* @param subject user that must have proper permissions
* @param bundleName name of the bundle to use (if not found, it will be created)
* @param bundleDescription optional long description of the bundle
* @param bundleTypeId the bundle type for the new bundle (if it is created) for which this will be the first version
* @param bundleGroupIds the bundle groups for the new bundle (if it is created) for which this will be the first version. null to leave unassigned.
* @param bundleVersionName name of the bundle version
* @param bundleVersionDescription optional long description of the bundle version
* @param version optional. If not supplied set to 1.0 for first version, or incremented (as best as possible) for subsequent version
* @return the persisted BundleVersion (id is assigned)
* @deprecated since 4.13 this is only used in tests - no need to have this in the API
*/
@Deprecated
BundleVersion createBundleAndBundleVersion(Subject subject, String bundleName, String bundleDescription,
int bundleTypeId, int[] bundleGroupIds, String bundleVersionName, String bundleVersionDescription,
String version, String recipe) throws Exception;
/**
* Internal use only, test entry point
* <pre>
* Required Permissions: Either:
* - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES
* - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG
* - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG
* </pre>
* @param subject user that must have proper permissions
* @param bundleId the bundle for which this will be the next version
* @param name not null or empty
* @param description optional long description of the bundle version
* @param version optional. If not supplied set to 1.0 for first version, or incremented (as best as possible) for subsequent version
* @return the persisted BundleVersion (id is assigned)
*
* @deprecated since 4.13, use one of the create(Initial)BundleVersionVia* methods
*/
@Deprecated
BundleVersion createBundleVersion(Subject subject, int bundleId, String name, String description, String version,
String recipe) throws Exception;
/**
* Used internally for transaction demarcation purposes.
*
* @param bundle the bundle to create version of
* @param name the name of the bundle version
* @param version the version of the bundle version
* @param description the description of the bundle version
* @param recipe the recipe of the bundle version
* @param configurationDefinition the configuration definition of the deployment properties
* @return the created bundle version
* @throws Exception on error
* @since 4.13
*/
BundleVersion createBundleVersionInternal(Bundle bundle, String name, String version, String description,
String recipe, ConfigurationDefinition configurationDefinition) throws Exception;
/**
* Not generally called. For use by Server Side Plugins when registering a Bundle Plugin.
* </p>
* Required Permissions:
* - Global.CREATE_BUNDLES
* </p>
* @param subject
* @param name not null or empty
* @param resourceTypeId id of the ResourceType that handles this BundleType
* @return the persisted BundleType (id is assigned)
*/
BundleType createBundleType(Subject subject, String name, int resourceTypeId) throws Exception;
/**
* This is typically not called directly, typically scheduleBundleResourceDeployment() is called externally.
* This executes in a New Transaction and supports scheduleBundleResourceDeployment.
* </p>
* This method performs NO AUTHZ!
* </p>
*/
BundleResourceDeployment createBundleResourceDeploymentInNewTrans(Subject subject, int bundleDeploymentId,
int resourceId) throws Exception;
/**
* Similar to {@link BundleManagerRemote#createBundleDeployment(Subject, int, int, String, Configuration)} but
* supplies the internally generated deploymentName and has different transaction semantics. Useful when an
* slsb method needs to both create a deployment and schedules it prior to returning to an external caller.
* </p>
* This method performs NO AUTHZ!
* </p>
*/
public BundleDeployment createBundleDeploymentInNewTrans(Subject subject, int bundleVersionId,
int bundleDestinationId, String name, String description, Configuration configuration) throws Exception;
/**
* Used by GUI
* </p>
* Required Permissions: Either:
* - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES
* - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG
* - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG
* </p>
*
* @param subject
* @param bundleVersionId
* @return Map, filename to foundInBundleVersion
* @throws Exception
*/
HashMap<String, Boolean> getAllBundleVersionFilenames(Subject subject, int bundleVersionId) throws Exception;
/**
* Used by GUI. Needed by the Bundle Deploy and Revert wizards GUI to generate a deployment name for display.
* <pre>
* Required Permissions: Either:
* - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles)
* - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles)
* </pre>
*
* @param subject
* @param bundleDestinationId required
* @param bundleVersionId required for progressive deployment, -1 for revert
* @param prevDeploymentId required for revert deployment, -1 for progressive
* @return
*/
public String getBundleDeploymentName(Subject subject, int bundleDestinationId, int bundleVersionId,
int prevDeploymentId);
/**
* Internal use only. A special case method to build the pojo that can be sent to the agent to
* schedule the deployment request. Uses NOT_SUPPORTED transaction attribute to avoid having the cleaned pojo
* affect the persistence context.
* </p>
* This method performs NO AUTHZ!
* </p>
*
* @throws Exception
*/
public BundleScheduleRequest getScheduleRequest(Subject subject, int resourceDeploymentId,
boolean isCleanDeployment, boolean isRevert) throws Exception;
/**
* Used by GUI. The deployment must be PENDING or in a completed state.
* <pre>
* Required Permissions: Either:
* - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles)
* - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles)
* </pre>
*
* @param subject
* @param bundleDeploymentId
* @throws Exception if any part of the removal fails.
*/
void deleteBundleDeployment(Subject subject, int bundleDeploymentId) throws Exception;
/**
* Internal use only. Called internally to set deployment status. Typically to a completion status when deployment
* ends. Exists for transaction boundary reasons only.
* </p>
* This method performs NO AUTHZ!
* </p>
*
* @param subject
* @param resourceDeploymentId id of the resource deployment appending the history record
* @param status
* @return the updated {@link BundleResourceDeployment}
*/
BundleResourceDeployment setBundleResourceDeploymentStatusInNewTransaction(Subject subject,
int resourceDeploymentId, BundleDeploymentStatus status) throws Exception;
/**
* Internal use only
* </p>
* 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.
* </p>
* This method performs NO AUTHZ!
* </p>
*
* @param subject
* @param bundleDeployment
* @param failedToPurge
* @throws Exception
*/
void _finalizePurge(Subject subject, BundleDeployment bundleDeployment,
Map<BundleResourceDeployment, String> failedToPurge) throws Exception;
/**
* Like {@link #createBundleVersionViaFile(Subject, File)} with one additional feature.
* This method exists solely to support the GUI's wizard workflow which always first tries to create a bundle
* version for an existing bundle, because it does not know whether this is an initial bundle version (only
* the server can figure that out after it cracks open the bundle distribution, parses the recipe, and
* looks for the bundle). If this is an initialBundleVersion this method does two things. First, it stores the
* distribution file as a temp file, this is done to avoid having to upload the file a second time. Second, it
* throws IllegalStateException with special message text, a token that can be sent back to
* {@link #createInitialBundleVersionViaToken(Subject, int[], String)}.
*/
BundleVersion createOrStoreBundleVersionViaFile(Subject subject, File distributionFile) throws Exception;
/**
* Like {@link #createBundleVersionViaURL(Subject, String, String, String)} with one additional feature.
* This method exists solely to support the GUI's wizard workflow which always first tries to create a bundle
* version for an existing bundle, because it does not know whether this is an initial bundle version (only
* the server can figure that out after it cracks open the bundle distribution, parses the recipe, and
* looks for the bundle). If this is an initialBundleVersion this method does two things. First, it stores the
* distribution file as a temp file, this is done to avoid having to upload the file a second time. Second, it
* throws IllegalStateException with special message text, a token that can be sent back to
* {@link #createInitialBundleVersionViaToken(Subject, int[], String)}.
*/
BundleVersion createOrStoreBundleVersionViaURL(Subject subject, String distributionFileUrl, String username,
String password) throws Exception;
/**
* This method exists solely to support the GUI's wizard workflow which always first tries to create a bundle
* version for an existing bundle, because it does not know whether this is an initial bundle version (only
* the server can figure that out after it cracks open the bundle distribution, parses the recipe, and
* looks for the bundle). It works in conjunction with {@link #createOrStoreBundleVersionViaFile(Subject, File)} or
* {@link #createOrStoreBundleVersionViaURL(Subject, String, String, String)}.
* <p/>
* This method will use the supplied token to access the distribution file. It assumes this is a new bundle and
* is responsible for creating the bundle as well as the bundle version. The caller can indicate which bundle
* groups the new bundle should be assigned to. If bundleGroupId is null, then the new bundle will not be
* associated with any bundle group - this is only allowed if the caller has the permission Global.VIEW_BUNDLES.
* <pre>
* Required Permissions: Either:
* - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES
* - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG
* - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG
* </pre>
* @param subject user that must have proper permissions
* @param bundleGroupIds identifies the bundle groups that the new bundle will be associated with; null or zero
* length to leave unassigned.
* @param token the token used to identify the distribution file stashed as a temp file.
* @return the persisted BundleVersion with a lot of the internal relationships filled in to help the caller
* understand all that this method did.
*/
BundleVersion createInitialBundleVersionViaToken(Subject subject, int[] bundleGroupIds, String token)
throws Exception;
/**
* For the calling subject determines which bundle groups to which the user can assign the bundle. The composite
* includes a <code>Map<BundleGroup,Boolean></code> indicating the assignable BundleGroups and which are
* currently assigned. It also indicates whether the bundle can be left unassigned. When querying for
* new bundles the bundleId should be set to 0.
*
* @param subject, the calling subject
* @param assigningSubject, the subject relevant to the bundle group assignment
* @param bundleId, the bundle relevant to the bundle group assignment, or 0 for a new bundle
* @return
* @throws Exception
*/
BundleGroupAssignmentComposite getAssignableBundleGroups(Subject subject, Subject assigningSubject, int bundleId)
throws Exception;
/**
* Determines (and updates) the deployment status of the provided bundle deployment based on the deployment statuses
* of the underlying resource deployments.
*
* @param bundleDeploymentId the id of the bundle deployment to check
* @return the determined bundle deployment status
*
* @since 4.10
*/
BundleDeploymentStatus determineBundleDeploymentStatus(int bundleDeploymentId);
/**
* Internal use only. Exists for transaction boundary reasons only.
* </p>
* This method performs NO AUTHZ!
* </p>
*/
BundleDeployment scheduleBundleDeploymentInNewTransaction(Subject subject, int bundleDeploymentId,
boolean isCleanDeployment, boolean isRevert, Integer revertedDeploymentReplacedDeployment) throws Exception;
/**
* Deletes all Bundles, Bundle types connected to given resource type
* @param subject
* @param resourceType
* @throws Exception
*/
void deleteMetadata(Subject subject, ResourceType resourceType) throws Exception;
}