/* * Copyright (c) 2012-2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.systemservices.impl.resource; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.POST; import javax.ws.rs.Produces; import javax.ws.rs.PUT; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import static com.emc.storageos.coordinator.client.model.Constants.DOWNLOADINFO_KIND; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.emc.storageos.coordinator.client.model.DownloadingInfo; import com.emc.storageos.coordinator.client.model.Site; import com.emc.storageos.coordinator.client.model.SiteState; import com.emc.storageos.coordinator.client.service.DrUtil; import com.emc.vipr.model.sys.NodeProgress.DownloadStatus; import com.emc.storageos.coordinator.client.model.RepositoryInfo; import com.emc.storageos.coordinator.client.model.SoftwareVersion; import com.emc.storageos.coordinator.exceptions.InvalidSoftwareVersionException; import com.emc.storageos.security.authorization.CheckPermission; import com.emc.storageos.security.authorization.Role; import com.emc.storageos.svcs.errorhandling.resources.APIException; import com.emc.storageos.svcs.errorhandling.resources.ServiceUnavailableException; import com.emc.storageos.systemservices.impl.property.PropertyManager; import com.emc.storageos.systemservices.impl.security.SecretsManager; import com.emc.storageos.systemservices.impl.upgrade.*; import com.emc.storageos.systemservices.impl.vdc.VdcManager; import com.emc.storageos.services.OperationTypeEnum; import com.emc.storageos.security.audit.AuditLogManager; import com.emc.storageos.security.upgradevoter.UpgradeVoter; import com.emc.vipr.model.sys.DownloadProgress; import com.emc.vipr.model.sys.ClusterInfo; import com.emc.vipr.model.sys.NodeProgress; import com.emc.vipr.model.sys.TargetVersionResponse; import static com.emc.storageos.coordinator.client.model.Constants.MAX_UPLOAD_SIZE; import static com.emc.storageos.systemservices.mapper.ClusterInfoMapper.setInstallableRemovable; import static com.emc.storageos.systemservices.mapper.ClusterInfoMapper.toClusterResponse; import com.emc.storageos.systemservices.exceptions.CoordinatorClientException; import com.emc.storageos.systemservices.exceptions.LocalRepositoryException; import com.emc.storageos.systemservices.exceptions.RemoteRepositoryException; @Path("/upgrade/") public class UpgradeService { private static final String VIPR_UNKNOWN_IMAGE_VERSION = "unknown"; private static final Logger _log = LoggerFactory.getLogger(UpgradeService.class); private static final String EVENT_SERVICE_TYPE = "upgrade"; private CoordinatorClientExt _coordinator = null; private UpgradeManager _upgradeManager = null; private DrUtil drUtil; private final static String FORCE = "1"; @Autowired private AuditLogManager _auditMgr; @Autowired private SecretsManager _secretsManager; @Autowired private PropertyManager _propertyManager; @Autowired private VdcManager _vdcManager; /** * Callback for other components to register itself for upgrade check before upgrade process starts. */ private List<UpgradeVoter> _upgradeVoters; public void setProxy(CoordinatorClientExt proxy) { _coordinator = proxy; } public void setUpgradeManager(UpgradeManager upgradeManager) { _upgradeManager = upgradeManager; } public void setUpgradeVoters(List<UpgradeVoter> voters) { _upgradeVoters = voters; } public void setDrUtil(DrUtil drUtil) { this.drUtil = drUtil; } /** * Upgrade target version. Refer to product documentation for valid upgrade paths. * * @brief Update the target version of the build * @param version The new version number * @prereq Target version should be installed and cluster state should be STABLE * @return Cluster state information. * @throws IOException */ @PUT @Path("target-version/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN }) public Response setTargetVersion(@QueryParam("version") String version, @QueryParam("force") String forceUpgrade) throws IOException { SoftwareVersion targetVersion = null; try { targetVersion = new SoftwareVersion(version); } catch (InvalidSoftwareVersionException e) { throw APIException.badRequests.parameterIsNotValid("version"); } // validate if (!_coordinator.isClusterUpgradable()) { throw APIException.serviceUnavailable.clusterStateNotStable(); } // check if all DR sites are in stable or paused status checkClusterState(true); List<SoftwareVersion> available = null; try { available = _coordinator.getVersions(_coordinator.getMySvcId()); } catch (CoordinatorClientException e) { throw APIException.internalServerErrors.getObjectFromError("available versions", "coordinator", e); } if (!available.contains(targetVersion)) { throw APIException.badRequests.versionIsNotAvailableForUpgrade(version); } // To Do - add a check for upgradable from current SoftwareVersion current = null; try { current = _coordinator.getRepositoryInfo(_coordinator.getMySvcId()) .getCurrentVersion(); } catch (CoordinatorClientException e) { throw APIException.internalServerErrors.getObjectFromError("current version", "coordinator", e); } if (!current.isSwitchableTo(targetVersion)) { throw APIException.badRequests.versionIsNotUpgradable(targetVersion.toString(), current.toString()); } // Check if allowed from upgrade voter and force option can veto if (FORCE.equals(forceUpgrade)) { _log.info("Force option supplied, skipping all geo/dr pre-checks"); } else { for (UpgradeVoter voter : _upgradeVoters) { voter.isOKForUpgrade(current.toString(), version); } } try { _coordinator.setTargetInfo(new RepositoryInfo(targetVersion, _coordinator.getTargetInfo(RepositoryInfo.class).getVersions())); } catch (Exception e) { throw APIException.internalServerErrors.setObjectToError("target version", "coordinator", e); } _log.info("target version changed successfully. new target {}", targetVersion); auditUpgrade(OperationTypeEnum.UPDATE_VERSION, AuditLogManager.AUDITLOG_SUCCESS, null, targetVersion.toString(), FORCE.equals(forceUpgrade)); ClusterInfo clusterInfo = _coordinator.getClusterInfo(); if (clusterInfo == null) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Cluster info"); } return toClusterResponse(clusterInfo); } /** * Show the current target version * * @brief Show the target version * @prereq none * @return Target version response */ @GET @Path("target-version/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public TargetVersionResponse getTargetVersion() { SoftwareVersion version = null; try { version = _coordinator.getTargetInfo(RepositoryInfo.class).getCurrentVersion(); } catch (Exception e) { throw APIException.internalServerErrors.getObjectFromError("current version", "coordinator", e); } TargetVersionResponse resp = new TargetVersionResponse(); resp.setTargetVersion(version.toString()); return resp; } /** * Show cluster state * * @brief Show cluster state * @param forceShow If force =, will show all removable versions even though the installed versions are less than MAX_SOFTWARE_VERSIONS * @prereq none * @return Cluster state information * @throws IOException */ @GET @Path("cluster-state/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.SECURITY_ADMIN, Role.SYSTEM_MONITOR }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public ClusterInfo getClusterState(@QueryParam("force") String forceShow, @QueryParam("site") String siteId) throws IOException { ClusterInfo clusterInfo = _coordinator.getClusterInfo(siteId); if (clusterInfo == null) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Cluster info"); } if (_upgradeManager.getRemoteRepository() != null) { try { Map<SoftwareVersion, List<SoftwareVersion>> cachedVersions = RemoteRepository.getCachedSoftwareVersions(); _log.info("The cached software versions are:" + cachedVersions.toString()); setInstallableRemovable(clusterInfo, _coordinator.getTargetInfo(RepositoryInfo.class), cachedVersions, FORCE.equals(forceShow)); } catch (IOException e) { throw e; } catch (Exception e) { throw APIException.internalServerErrors.getObjectFromError("target repository info", "coordinator", e); } } return clusterInfo; } /** * Install image. Image can be installed only if the number of installed images are less than MAX_SOFTWARE_VERSIONS * * @brief Install image * @param versionStr Version to be installed * @prereq Cluster state should be STABLE * @return Cluster state information * @throws Exception */ @POST @Path("image/install/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN }) public Response installImage(@QueryParam("version") String versionStr) throws Exception { _log.info("installImage({})", versionStr); final SoftwareVersion version; try { version = new SoftwareVersion(versionStr); } catch (InvalidSoftwareVersionException e) { throw APIException.badRequests.parameterIsNotValid("version"); } // do not proceed if there's paused sites. checkClusterState(false); RepositoryInfo repoInfo = null; try { repoInfo = _coordinator.getTargetInfo(RepositoryInfo.class); } catch (Exception e) { throw APIException.internalServerErrors.getObjectFromError("target repository info", "coordinator", e); } SoftwareVersion currentVersion = repoInfo.getCurrentVersion(); List<SoftwareVersion> localAvailableVersions = repoInfo.getVersions(); if (localAvailableVersions.size() > SyncInfoBuilder.MAX_SOFTWARE_VERSIONS) { throw APIException.badRequests.numberOfInstalledExceedsMax(); } RemoteRepository repo = _upgradeManager.getRemoteRepository(); if (isInstalled(repoInfo.getVersions(), version)) { throw APIException.badRequests.versionIsInstalled(versionStr); } if (!isUpgradable(repoInfo.getCurrentVersion(), version)) { throw APIException.badRequests.versionIsNotAvailableForUpgrade(versionStr); } try { // check that the version can be downloaded from the remote repository repo.checkVersionDownloadable(version); } catch (RemoteRepositoryException e) { throw APIException.internalServerErrors.getObjectError("remote repository info", e); } List<SoftwareVersion> newList = new ArrayList<SoftwareVersion>(localAvailableVersions); newList.add(version); int versionSize = repo.checkVersionSize(version); _log.info("The size of the image is:" + versionSize); initializeDownloadProgress(versionStr, versionSize); try { _coordinator.setTargetInfo( new RepositoryInfo(currentVersion, newList)); } catch (Exception e) { throw APIException.internalServerErrors.setObjectToError("target versions", "coordinator", e); } auditUpgrade(OperationTypeEnum.INSTALL_IMAGE, AuditLogManager.AUDITLOG_SUCCESS, null, versionStr); ClusterInfo clusterInfo = _coordinator.getClusterInfo(); if (clusterInfo == null) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Cluster info"); } return toClusterResponse(clusterInfo); } private void checkClusterState(boolean skipPausedSites) { for (Site site : drUtil.listSites()) { if (site.getState() == SiteState.STANDBY_PAUSED) { if (skipPausedSites) { continue; } else { _log.error("Site {} is paused, stop proceeding image downloading request", site.getUuid()); throw APIException.serviceUnavailable.sitePaused(site.getName()); } } ClusterInfo.ClusterState state = _coordinator.getCoordinatorClient().getControlNodesState(site.getUuid()); if (state != ClusterInfo.ClusterState.STABLE) { _log.error("Site {} is not stable: {}", site.getUuid(), state); throw APIException.serviceUnavailable.siteClusterStateNotStable(site.getName(), state.toString()); } } } /** * Check if a version is installed or not. * true If the version is the same as one of the local available versions. * * @param localAvailableVersions available versions * @param targetVersion version * @return true or false */ private boolean isInstalled(List<SoftwareVersion> localAvailableVersions, SoftwareVersion targetVersion) { for (SoftwareVersion s : localAvailableVersions) { if (targetVersion.compareTo(s) == 0) { return true; } } return false; } /** * Check if a version is upgradable or not. * * @param currentVersion version * @param targetVersion version * @return true or false */ private boolean isUpgradable(SoftwareVersion currentVersion, SoftwareVersion targetVersion) throws Exception { if (currentVersion.isNaturallySwitchableTo(targetVersion)) { return true; } RemoteRepository repo = _upgradeManager.getRemoteRepository(); for (SoftwareVersion v : repo.getUpgradeFromVersions(targetVersion)) { if (v.weakEquals(currentVersion)) { return true; } } return false; } /** * For download progress monitoring, The zookeeper structure used in the setNodeGlobalScopeInfo() and getNodeGlobalScopeInfo() is * /sites/(site_uuid)/config/downloadinfo/(svcId) * Each node has a entry in the coordinator indicated by its svcId. * The remote download and internode download are monitored in the same way, because the process is the same in the UpgradeImageCommon * class. * Every second if the newly downloaded bytes are more that 1MB, we update the progress entry in the coordinator. * For the cancel function, it first check the progress entries in the coordinator to see if there is a download in progress, if there * is, get the * version from the entry, and erase this version from the target RepositoryInfo object in the coordinator. This operation will * terminate the ongoing download process. */ /** * Check the version downloading progress. the downloading could be from remote repository * * @return image downloading progress * @throws Exception */ @GET @Path("image/download/progress/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public DownloadProgress checkDownloadProgress(@QueryParam("site") String siteId, @Context HttpHeaders headers) throws Exception { _log.info("checkDownloadProgress()"); DownloadProgress progress = new DownloadProgress(); DownloadingInfo targetDownloadInfo = _coordinator.getTargetInfo(DownloadingInfo.class); if (targetDownloadInfo == null || targetDownloadInfo._status == DownloadStatus.CANCELLED) { // return empty progress. No download in progress return progress; } progress.setImageSize(targetDownloadInfo._size); for (String svcId : _coordinator.getAllNodes(siteId)) { DownloadingInfo downloadInfo = _coordinator.getNodeGlobalScopeInfo(DownloadingInfo.class, siteId, DOWNLOADINFO_KIND, svcId); if (null == downloadInfo) { progress.addNodeProgress(svcId, new NodeProgress(0, DownloadStatus.NORMAL, 0, 0)); } else { int downloadErrorCount = downloadInfo._errorCounter.get(0); int checksumErrorCount = downloadInfo._errorCounter.get(1); progress.addNodeProgress(svcId, new NodeProgress(downloadInfo.downloadedBytes, downloadInfo._status, downloadErrorCount, checksumErrorCount)); } } return progress; } /** * Cancel installing a version or uploading a version. Remove it from the target RepositoryInfo * * @prereq There should be image downloading in progress. * @return Cluster state information * @throws IOException */ @POST @Path("image/install/cancel/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN }) public Response cancelInstallingOrUploadingImage() throws IOException { _log.info("cancelInstallingOrUploadingImage()"); DownloadingInfo downloadInfo = null; boolean inProgressFlag = false; DownloadingInfo downloadTargetInfo; try { downloadTargetInfo = _coordinator.getTargetInfo(DownloadingInfo.class); } catch (Exception e1) { throw APIException.internalServerErrors.getObjectFromError("Target downloading info", "coordinator", e1); } if (null == downloadTargetInfo || DownloadStatus.CANCELLED == downloadTargetInfo._status) { // Check the target info of the // DownloadingInfo class to see if user // sent a cancel request inProgressFlag = false; // No previous installation/upload or installation/upload got cancelled, not in progress } for (String svcId : _coordinator.getAllNodes()) { DownloadingInfo tmpInfo; try { tmpInfo = _coordinator.getNodeGlobalScopeInfo(DownloadingInfo.class, DOWNLOADINFO_KIND, svcId); } catch (Exception e) { throw APIException.internalServerErrors.getObjectFromError("Node downloading info", "coordinator", e); } if (null != tmpInfo && tmpInfo._status != DownloadStatus.COMPLETED) { downloadInfo = tmpInfo; inProgressFlag = true; break; } } if (!inProgressFlag) { throw APIException.badRequests.noDownloadInProgress(); } String installingVersion = downloadInfo._version; if (installingVersion.equals(VIPR_UNKNOWN_IMAGE_VERSION)) { throw ServiceUnavailableException.serviceUnavailable.versionOfTheImageIsUnknownSoFar(); } _coordinator.setTargetInfo(downloadInfo.cancel(), false); return removeImage(installingVersion, "1"); } /** * Remove an image. Image can be removed only if the number of installed images are * greater than MAX_SOFTWARE_VERSIONS * * @brief Remove an image * @param versionStr Version to be removed * @param forceRemove If force=1, image will be removed even if the maximum number of versions installed are less than * MAX_SOFTWARE_VERSIONS * @prereq Image should be installed and cluster state should be STABLE * @return Cluster state information * @throws IOException */ @POST @Path("image/remove/") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN }) public Response removeImage(@QueryParam("version") String versionStr, @QueryParam("force") String forceRemove) throws IOException { _log.info("removeImage({})", versionStr); final SoftwareVersion version; try { version = new SoftwareVersion(versionStr); } catch (InvalidSoftwareVersionException e) { throw APIException.badRequests.parameterIsNotValid("version"); } RepositoryInfo targetInfo = null; try { targetInfo = _coordinator.getTargetInfo(RepositoryInfo.class); } catch (Exception e) { throw APIException.internalServerErrors.getObjectFromError("target repository info", "coordinator", e); } final SyncInfo remoteSyncInfo = SyncInfoBuilder.removableVersions(targetInfo, FORCE.equals(forceRemove)); if (remoteSyncInfo.isEmpty() || remoteSyncInfo.getToRemove() == null || !remoteSyncInfo.getToRemove().contains(version)) { throw APIException.badRequests.versionIsNotRemovable(versionStr); } List<SoftwareVersion> newList = new ArrayList<SoftwareVersion>(targetInfo.getVersions()); newList.remove(version); try { _coordinator.setTargetInfo( new RepositoryInfo(targetInfo.getCurrentVersion(), newList), !FORCE.equals(forceRemove)); } catch (Exception e) { throw APIException.internalServerErrors.setObjectToError("target versions", "coordinator", e); } auditUpgrade(OperationTypeEnum.REMOVE_IMAGE, AuditLogManager.AUDITLOG_SUCCESS, null, versionStr, FORCE.equals(forceRemove)); ClusterInfo clusterInfo = _coordinator.getClusterInfo(); if (clusterInfo == null) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Cluster info"); } return toClusterResponse(clusterInfo); } /** * *Internal API, used only between nodes* * <p> * Get image * * @param versionStr Version to be retrieved * @return Image details */ @GET @Path("internal/image/") @Produces({ MediaType.APPLICATION_OCTET_STREAM }) public Response getImage(@QueryParam("version") String versionStr) { _log.info("getImage({})", versionStr); final SoftwareVersion version; try { version = new SoftwareVersion(versionStr); } catch (InvalidSoftwareVersionException e) { throw APIException.badRequests.parameterIsNotValid("version"); } final InputStream in; try { in = LocalRepository.getInstance().getImageInputStream(version); } catch (LocalRepositoryException e) { throw APIException.internalServerErrors.getObjectFromError("image input stream", "local repository", e); } return Response.ok(in).type(MediaType.APPLICATION_OCTET_STREAM).build(); } /** * *Internal API, used only between nodes* * <p> * Wake up node * * @return Cluster state information. */ @POST @Path("internal/wakeup/") public Response wakeupManager(@QueryParam("type") String managerType) { if (managerType == null) { managerType = "all"; } switch (managerType) { case "upgrade": _upgradeManager.wakeup(); break; case "secrets": _secretsManager.wakeup(); break; case "property": _propertyManager.wakeup(); break; case "vdc": _vdcManager.wakeup(); break; default: _upgradeManager.wakeup(); _secretsManager.wakeup(); _propertyManager.wakeup(); _vdcManager.wakeup(); } ClusterInfo clusterInfo = _coordinator.getClusterInfo(); if (clusterInfo == null) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Cluster info"); } _log.debug("Successfully woke up {} manager(s)", managerType); return toClusterResponse(clusterInfo); } /** * Upload the image file given. * Consumes MediaType.APPLICATION_OCTET_STREAM. * This is an asynchronous operation. * * @brief Upload the specified image file * @prereq Cluster state should be STABLE * @return Cluster information. */ @POST @Path("image/upload") @CheckPermission(roles = { Role.SYSTEM_ADMIN, Role.RESTRICTED_SYSTEM_ADMIN }) @Consumes({ MediaType.APPLICATION_OCTET_STREAM }) @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) public Response uploadImage(@Context HttpServletRequest request) { File file = null; String svcId = _coordinator.getMySvcId(); _log.info("uploadImage to {} start", svcId); // validate if (!_coordinator.isClusterUpgradable()) { throw APIException.serviceUnavailable.clusterStateNotStable(); } // maximal install number check RepositoryInfo targetInfo = null; try { targetInfo = _coordinator.getTargetInfo(RepositoryInfo.class); } catch (Exception e) { throw APIException.internalServerErrors.getObjectFromError("target repository info", "coordinator", e); } if (targetInfo.getVersions().size() > SyncInfoBuilder.MAX_SOFTWARE_VERSIONS) { throw APIException.badRequests.numberOfInstalledExceedsMax(); } // length check String contentLength = request.getHeader("Content-Length"); if (Long.parseLong(contentLength) <= 0 || Long.parseLong(contentLength) > MAX_UPLOAD_SIZE) { throw APIException.badRequests.fileSizeExceedsLimit(MAX_UPLOAD_SIZE); } try { // remove previous and upload to a temp file UpgradeImageUploader uploader = UpgradeImageUploader.getInstance(_upgradeManager); uploader.cleanUploadFiles(); long versionSize = Long.valueOf(contentLength); _log.info("The size of the image is:" + versionSize); String version = VIPR_UNKNOWN_IMAGE_VERSION; initializeDownloadProgress(version, versionSize); file = uploader.startUpload(request.getInputStream(), version); // install image if (file == null || file != null && !file.exists()) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Uploaded file"); } version = _upgradeManager.getLocalRepository().installImage(file); // set target List<SoftwareVersion> newList = new ArrayList<SoftwareVersion>(targetInfo.getVersions()); SoftwareVersion newVersion = new SoftwareVersion(version); if (newList.contains(newVersion)) { _log.info("Version has already been installed"); } else { newList.add(newVersion); _coordinator.setTargetInfo(new RepositoryInfo(targetInfo.getCurrentVersion(), newList)); DownloadingInfo temp = _coordinator.getNodeGlobalScopeInfo(DownloadingInfo.class, DOWNLOADINFO_KIND, svcId); _coordinator.setNodeGlobalScopeInfo(new DownloadingInfo(version, versionSize, versionSize, DownloadStatus.COMPLETED, temp._errorCounter), DOWNLOADINFO_KIND, svcId); _coordinator.setTargetInfo(new DownloadingInfo(version, versionSize), false); } _log.info("uploadImage to {} end", svcId); auditUpgrade(OperationTypeEnum.UPLOAD_IMAGE, AuditLogManager.AUDITLOG_SUCCESS, null, targetInfo.getCurrentVersion().toString(), svcId); // return cluster status ClusterInfo clusterInfo = _coordinator.getClusterInfo(); if (clusterInfo == null) { throw APIException.internalServerErrors.targetIsNullOrEmpty("Cluster info"); } return toClusterResponse(clusterInfo); } catch (APIException ae) { throw ae; } catch (Exception e) { throw APIException.internalServerErrors.uploadInstallError(e); } finally { if (file != null && file.exists()) { file.delete(); } } } /** * Initialize download progress for each node * * @param version - the version that is being downloaded * @param versionSize - the size of the image file */ private void initializeDownloadProgress(String version, long versionSize) { _coordinator.setTargetInfo(new DownloadingInfo(version, versionSize)); for (Site site : drUtil.listSites()) { for (String nodeId : _coordinator.getAllNodes(site.getUuid())) { _coordinator.setNodeGlobalScopeInfo(new DownloadingInfo(version, versionSize), site.getUuid(), DOWNLOADINFO_KIND, nodeId); } } } /** * Record audit log for upgrade service * * @param auditType Type of AuditLog * @param operationalStatus Status of operation * @param description Description for the AuditLog * @param descparams Description parameters */ public void auditUpgrade(OperationTypeEnum auditType, String operationalStatus, String description, Object... descparams) { _auditMgr.recordAuditLog(null, null, EVENT_SERVICE_TYPE, auditType, System.currentTimeMillis(), operationalStatus, description, descparams); } }