diff --git a/src/main/java/org/icatproject/topcat/StatusCheck.java b/src/main/java/org/icatproject/topcat/StatusCheck.java index 33c13006..425fce1e 100644 --- a/src/main/java/org/icatproject/topcat/StatusCheck.java +++ b/src/main/java/org/icatproject/topcat/StatusCheck.java @@ -218,35 +218,61 @@ private void sendDownloadReadyEmail(Download download) throws InternalException{ } } - private void prepareDownload(Download download, IdsClient injectedIdsClient) throws Exception { + /** + * Public static method for external calls to prepare a Download. + * + * @param downloadRepository DownloadRepository to save the updated Download + * @param download Download to prepare + * @param sessionId ICAT sessionId to use, possibly different from + * the one set on the Download if it has expired + * @param injectedIdsClient Optional (possibly mock) IdsClient + * @throws TopcatException If prepareData fails + */ + public static void prepareDownload(DownloadRepository downloadRepository, Download download, String sessionId, + IdsClient injectedIdsClient) throws TopcatException { + + IdsClient idsClient = injectedIdsClient; + if( idsClient == null ) { + idsClient = new IdsClient(getDownloadUrl(download.getFacilityName(),download.getTransport())); + } + logger.info("Requesting prepareData for Download " + download.getFileName()); + String preparedId = idsClient.prepareData(sessionId, download.getInvestigationIds(), download.getDatasetIds(), + download.getDatafileIds()); + download.setPreparedId(preparedId); try { - IdsClient idsClient = injectedIdsClient; - if( idsClient == null ) { - idsClient = new IdsClient(getDownloadUrl(download.getFacilityName(),download.getTransport())); - } - logger.info("Requesting prepareData for Download " + download.getFileName()); - String preparedId = idsClient.prepareData(download.getSessionId(), download.getInvestigationIds(), download.getDatasetIds(), download.getDatafileIds()); - download.setPreparedId(preparedId); - - try { - Long size = idsClient.getSize(download.getSessionId(), download.getInvestigationIds(), download.getDatasetIds(), download.getDatafileIds()); - download.setSize(size); - } catch(Exception e) { - logger.error("prepareDownload: setting size to -1 as getSize threw exception: " + e.getMessage()); - download.setSize(-1); - } + Long size = idsClient.getSize(sessionId, download.getInvestigationIds(), download.getDatasetIds(), + download.getDatafileIds()); + download.setSize(size); + } catch(Exception e) { + logger.error("prepareDownload: setting size to -1 as getSize threw exception: " + e.getMessage()); + download.setSize(-1); + } - if (download.getIsTwoLevel() || !download.getTransport().matches("https|http")) { - logger.info("Setting Download status RESTORING for " + download.getFileName()); - download.setStatus(DownloadStatus.RESTORING); - } else { - logger.info("Setting Download status COMPLETE for " + download.getFileName()); - download.setStatus(DownloadStatus.COMPLETE); - download.setCompletedAt(new Date()); - } + if (download.getIsTwoLevel() || !download.getTransport().matches("https|http")) { + logger.info("Setting Download status RESTORING for " + download.getFileName()); + download.setStatus(DownloadStatus.RESTORING); + } else { + logger.info("Setting Download status COMPLETE for " + download.getFileName()); + download.setStatus(DownloadStatus.COMPLETE); + download.setCompletedAt(new Date()); + } + + downloadRepository.save(download); + } - downloadRepository.save(download); + /** + * Private method for internal calls to prepare a Download. Exceptions will + * be handled if possible, and the Download might be marked as EXPIRED as + * part of this process. + * + * @param download Download to prepare + * @param injectedIdsClient Optional (possibly mock) IdsClient + * @throws Exception If internal exceptions could not be handled + */ + private void prepareDownload(Download download, IdsClient injectedIdsClient) throws Exception { + try { + prepareDownload(downloadRepository, download, download.getSessionId(), injectedIdsClient); } catch(NotFoundException e){ handleException(download, "prepareDownload NotFoundException: " + e.getMessage()); } catch(TopcatException e) { @@ -255,7 +281,6 @@ private void prepareDownload(Download download, IdsClient injectedIdsClient) thr } catch(Exception e){ handleException(download, "prepareDownload Exception: " + e.toString()); } - } private void handleException( Download download, String reason, boolean doExpire ) { @@ -277,7 +302,7 @@ private void handleException( Download download, String reason ) { handleException( download, reason, false ); } - private String getDownloadUrl( String facilityName, String downloadType ) throws InternalException{ + private static String getDownloadUrl( String facilityName, String downloadType ) throws InternalException{ return FacilityMap.getInstance().getDownloadUrl(facilityName, downloadType); } } diff --git a/src/main/java/org/icatproject/topcat/web/rest/AdminResource.java b/src/main/java/org/icatproject/topcat/web/rest/AdminResource.java index f8bcc154..bbd12429 100644 --- a/src/main/java/org/icatproject/topcat/web/rest/AdminResource.java +++ b/src/main/java/org/icatproject/topcat/web/rest/AdminResource.java @@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory; import org.icatproject.topcat.FacilityMap; import org.icatproject.topcat.IcatClient; +import org.icatproject.topcat.StatusCheck; @Stateless @LocalBean @@ -184,7 +185,42 @@ public Response setDownloadStatus( return Response.ok().build(); } - + + /** + * Prepare a possibly expired or deleted Download. Any completion or + * deletion date will be unset and isDeleted set to false. A new call to + * the IDS will generate a new preparedId and put the job in the RESTORING + * state. + * + * @param id Download.id + * @param facilityName ICAT Facility.name + * @param sessionId ICAT sessionId + * @return OK 200 if successful + * @throws MalformedURLException if facilityName is invalid. + * @throws TopcatException if anything else goes wrong. + */ + @PUT + @Path("/download/{id}/prepare") + @Produces({MediaType.APPLICATION_JSON}) + public Response prepareDownload(@PathParam("id") Long id, @FormParam("facilityName") String facilityName, + @FormParam("sessionId") String sessionId) throws TopcatException, MalformedURLException { + + String icatUrl = getIcatUrl(facilityName); + onlyAllowAdmin(icatUrl, sessionId); + + Download download = downloadRepository.getDownload(id); + if(download == null){ + throw new NotFoundException("could not find download"); + } + + download.setIsDeleted(false); + download.setDeletedAt(null); + download.setCompletedAt(null); + StatusCheck.prepareDownload(downloadRepository, download, sessionId, null); + + return Response.ok().build(); + } + /** * Sets whether or not a download is deleted. * diff --git a/src/test/java/org/icatproject/topcat/AdminResourceTest.java b/src/test/java/org/icatproject/topcat/AdminResourceTest.java index a223f82b..fef55932 100644 --- a/src/test/java/org/icatproject/topcat/AdminResourceTest.java +++ b/src/test/java/org/icatproject/topcat/AdminResourceTest.java @@ -1,6 +1,7 @@ package org.icatproject.topcat; import java.util.*; +import java.util.Date; import java.io.File; import java.lang.reflect.*; @@ -309,6 +310,42 @@ public void testSetDownloadTypeStatus() throws Exception { } } + @Test + public void testPrepareDownload() throws Exception { + Long downloadId = null; + try { + Download testDownload = new Download(); + String facilityName = "LILS"; + testDownload.setFacilityName(facilityName); + testDownload.setSessionId(adminSessionId); + testDownload.setStatus(DownloadStatus.EXPIRED); + testDownload.setIsDeleted(true); + testDownload.setIsTwoLevel(true); + testDownload.setDeletedAt(new Date()); + testDownload.setUserName("simple/root"); + testDownload.setFileName("testFile.txt"); + testDownload.setTransport("http"); + downloadRepository.save(testDownload); + downloadId = testDownload.getId(); + + Response response = adminResource.prepareDownload(downloadId, facilityName, adminSessionId); + assertEquals(200, response.getStatus()); + + response = adminResource.getDownloads(facilityName, adminSessionId, null); + assertEquals(200, response.getStatus()); + List downloads = (List) response.getEntity(); + + testDownload = findDownload(downloads, downloadId); + assertEquals(DownloadStatus.RESTORING, testDownload.getStatus()); + assertFalse(testDownload.getIsDeleted()); + assertNull(testDownload.getDeletedAt()); + } finally { + if (downloadId != null) { + downloadRepository.removeDownload(downloadId); + } + } + } + @Test public void testClearCachedSize() throws Exception { diff --git a/tools/datagateway_admin b/tools/datagateway_admin index 7cd97858..6d9ca4fb 100644 --- a/tools/datagateway_admin +++ b/tools/datagateway_admin @@ -150,38 +150,16 @@ def list_file_locations(): def prepare_download(): - download_id = input("Enter download id: ") - investigation_ids = [] - dataset_ids = [] - datafile_ids = [] - download = json.loads(requests.get(topcat_url + "/admin/downloads", params={ - "facilityName": facility_name, - "sessionId": session_id, - "queryOffset": "where download.id = " + download_id - }, verify=verifySsl).text)[0] - download_items = download["downloadItems"] - for download_item in download_items: - if download_item["entityType"] == "investigation": - investigation_ids.append(download_item["entityId"]) - elif download_item["entityType"] == "dataset": - dataset_ids.append(download_item["entityId"]) - elif download_item["entityType"] == "datafile": - datafile_ids.append(download_item["entityId"]) - params = { - "zip": "true", - "sessionId": session_id - } - if (len(investigation_ids) > 0): - params["investigationIds"] = ",".join(map(str, investigation_ids)) - if (len(dataset_ids) > 0): - params["datasetIds"] = ",".join(map(str, dataset_ids)) - if (len(datafile_ids) > 0): - params["datafileIds"] = ",".join(map(str, datafile_ids)) - prepared_id = requests.post(ids_url + "/prepareData", data=params, verify=verifySsl).text - print("") - print("UPDATE DOWNLOAD set PREPARED_ID = '" + prepared_id + "', STATUS = 'RESTORING' WHERE ID = " + download_id) - - + download_ids = input("Enter one or more space separated download id(s): ") + for download_id in download_ids.split(): + requests.post( + f"{topcat_url}/admin/download/{download_id}/prepare", + params={ + "facilityName": facility_name, + "sessionId": session_id, + }, + verify=verifySsl, + ) def expire_download(): @@ -293,7 +271,7 @@ while True: print("What do you want to do?") print(" * 1: Show download.") print(" * 2: Get a list of all the file locations for a download.") - print(" * 3: Create preparedId for a download and generate update SQL.") + print(" * 3: Prepare download(s).") print(" * 4: Set a download status to 'EXPIRED'.") print(" * 5: Expire all pending downloads.") print(" * 6: Enable or disable download types.")