From 7681799a78ff9ddf412e4ed7546d3f04c8160e5b Mon Sep 17 00:00:00 2001 From: Sonia Zorba Date: Sat, 9 Jan 2021 10:23:51 +0100 Subject: [PATCH] Implemented basic synchronous pullFromVoSpace --- .../java/it/inaf/oats/vospace/JobService.java | 26 ++++++- .../inaf/oats/vospace/TransferController.java | 75 +++++++++++++------ .../java/it/inaf/oats/vospace/UriService.java | 24 +++++- 3 files changed, 97 insertions(+), 28 deletions(-) diff --git a/src/main/java/it/inaf/oats/vospace/JobService.java b/src/main/java/it/inaf/oats/vospace/JobService.java index 9e1a59a..9beca1e 100644 --- a/src/main/java/it/inaf/oats/vospace/JobService.java +++ b/src/main/java/it/inaf/oats/vospace/JobService.java @@ -26,7 +26,21 @@ public class JobService { copyNode } - public void startJob(JobSummary job) { + public void setJobPhase(JobSummary job, String phase) { + + // TODO: check allowed job phase transitions + switch (phase) { + case "RUN": + startJob(job); + break; + case "ABORT": + throw new UnsupportedOperationException("Not implemented yet"); + default: + throw new IllegalArgumentException("Invalid phase parameter: " + phase); + } + } + + private void startJob(JobSummary job) { switch (getJobType(job)) { case pullToVoSpace: @@ -58,4 +72,14 @@ public class JobService { return JobType.valueOf(transfer.getDirection()); } + + /** + * Synchronous transfer endpoint creates a job that is immediately set to + * completed. + */ + public void createSyncJobResult(JobSummary job) { + job.setPhase(ExecutionPhase.COMPLETED); + uriService.setSyncTransferEndpoints(job); + jobDAO.createJob(job); + } } diff --git a/src/main/java/it/inaf/oats/vospace/TransferController.java b/src/main/java/it/inaf/oats/vospace/TransferController.java index f30583f..271a998 100644 --- a/src/main/java/it/inaf/oats/vospace/TransferController.java +++ b/src/main/java/it/inaf/oats/vospace/TransferController.java @@ -35,26 +35,32 @@ public class TransferController { @PostMapping(value = "/transfers", consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) - public ResponseEntity postTransfer(@RequestBody Transfer transfer, + public ResponseEntity postAsyncTransfer(@RequestBody Transfer transfer, @RequestParam(value = "PHASE", required = false) Optional phase, User principal) { - String jobId = UUID.randomUUID().toString().replace("-", ""); - - JobSummary jobSummary = new JobSummary(); - jobSummary.setJobId(jobId); - jobSummary.setOwnerId(principal.getName()); - jobSummary.setPhase(ExecutionPhase.PENDING); - JobSummary.JobInfo jobInfo = new JobSummary.JobInfo(); - jobInfo.getAny().add(transfer); - jobSummary.setJobInfo(jobInfo); + JobSummary jobSummary = newJobSummary(transfer, principal); jobDAO.createJob(jobSummary); - if (phase.isPresent() && "RUN".equals(phase.get())) { - jobService.startJob(jobSummary); + if (phase.isPresent()) { + jobService.setJobPhase(jobSummary, phase.get()); } - return getJobRedirect(jobId); + return getJobRedirect(jobSummary.getJobId()); + } + + @PostMapping(value = "/synctrans", + consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, + produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity postSyncTransfer(@RequestBody Transfer transfer, User principal) { + + JobSummary jobSummary = newJobSummary(transfer, principal); + + jobService.createSyncJobResult(jobSummary); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Location", request.getContextPath() + "/transfers/" + jobSummary.getJobId() + "/results/transferDetails"); + return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER); } @GetMapping(value = "/transfers/{jobId}", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) @@ -70,22 +76,45 @@ public class TransferController { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } - // TODO: check allowed job phase transitions - switch (phase) { - case "RUN": - jobService.startJob(job); - break; - case "ABORT": - throw new UnsupportedOperationException("Not implemented yet"); - default: - throw new IllegalArgumentException("Invalid phase parameter: " + phase); + return getJobRedirect(job.getJobId()); + + }).orElse(ResponseEntity.notFound().build()); + } + + @GetMapping(value = "/transfers/{jobId}/results/transferDetails", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity getTransferDetails(@PathVariable("jobId") String jobId, User principal) { + + return jobDAO.getJob(jobId).map(job -> { + if (!job.getOwnerId().equals(principal.getName())) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } - return getJobRedirect(job.getJobId()); + // TODO: check type + return ResponseEntity.ok((Transfer) (job.getJobInfo().getAny().get(0))); }).orElse(ResponseEntity.notFound().build()); } + @GetMapping(value = "/transfers/{jobId}/phase", produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getTransferJobPhase(@PathVariable("jobId") String jobId, User principal) { + // TODO: error handling + return ResponseEntity.ok(jobDAO.getJob(jobId).get().getPhase().toString()); + } + + private JobSummary newJobSummary(Transfer transfer, User principal) { + String jobId = UUID.randomUUID().toString().replace("-", ""); + + JobSummary jobSummary = new JobSummary(); + jobSummary.setJobId(jobId); + jobSummary.setOwnerId(principal.getName()); + jobSummary.setPhase(ExecutionPhase.PENDING); + JobSummary.JobInfo jobInfo = new JobSummary.JobInfo(); + jobInfo.getAny().add(transfer); + jobSummary.setJobInfo(jobInfo); + + return jobSummary; + } + private ResponseEntity getJobRedirect(String jobId) { HttpHeaders headers = new HttpHeaders(); headers.set("Location", request.getContextPath() + "/transfers/" + jobId); diff --git a/src/main/java/it/inaf/oats/vospace/UriService.java b/src/main/java/it/inaf/oats/vospace/UriService.java index 0d28a0e..e9272eb 100644 --- a/src/main/java/it/inaf/oats/vospace/UriService.java +++ b/src/main/java/it/inaf/oats/vospace/UriService.java @@ -6,6 +6,7 @@ import java.util.List; import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.uws.v1.ResultReference; import net.ivoa.xml.vospace.v2.Node; +import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Transfer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -28,16 +29,26 @@ public class UriService { List results = new ArrayList<>(); ResultReference result = new ResultReference(); - result.setHref(getUri(job)); + result.setHref(getEndpoint(job)); results.add(result); job.setResults(results); } - private String getUri(JobSummary job) { + public void setSyncTransferEndpoints(JobSummary job) { - // TODO add checks on data type - Transfer transfer = (Transfer) job.getJobInfo().getAny().get(0); + Transfer transfer = getTransfer(job); + + Protocol protocol = new Protocol(); + protocol.setUri("ivo://ivoa.net/vospace/core#httpget"); + protocol.setEndpoint(getEndpoint(job)); + + transfer.getProtocols().add(protocol); + } + + private String getEndpoint(JobSummary job) { + + Transfer transfer = getTransfer(job); String relativePath = transfer.getTarget().substring("vos://".length() + authority.length()); @@ -49,4 +60,9 @@ public class UriService { // TODO add token for authenticated access return fileServiceUrl + relativePath + "?jobId=" + job.getJobId(); } + + private Transfer getTransfer(JobSummary job) { + // TODO add checks on data type + return (Transfer) job.getJobInfo().getAny().get(0); + } } -- GitLab