From 30a1b3ce6d78f3740dcb168d01d0fe38a9add5cb Mon Sep 17 00:00:00 2001 From: Sonia Zorba <sonia.zorba@inaf.it> Date: Fri, 18 Dec 2020 17:10:48 +0100 Subject: [PATCH] Implemented basic pullToVoSpace for tape recall --- pom.xml | 24 ++++++++ .../java/it/inaf/oats/vospace/JobService.java | 61 +++++++++++++++++++ .../it/inaf/oats/vospace/TapeService.java | 35 +++++++++++ .../inaf/oats/vospace/TransferController.java | 20 +++--- .../oats/vospace/TransferControllerTest.java | 2 +- 5 files changed, 133 insertions(+), 9 deletions(-) create mode 100644 src/main/java/it/inaf/oats/vospace/JobService.java create mode 100644 src/main/java/it/inaf/oats/vospace/TapeService.java diff --git a/pom.xml b/pom.xml index 93583c8..ae00961 100644 --- a/pom.xml +++ b/pom.xml @@ -81,6 +81,11 @@ <version>2.0.0-SNAPSHOT</version> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-amqp</artifactId> + </dependency> + <!-- Embedded PostgreSQL: --> <dependency> <groupId>com.opentable.components</groupId> @@ -116,6 +121,25 @@ <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> + <plugin> + <groupId>org.jacoco</groupId> + <artifactId>jacoco-maven-plugin</artifactId> + <version>0.8.6</version> + <executions> + <execution> + <goals> + <goal>prepare-agent</goal> + </goals> + </execution> + <execution> + <id>report</id> + <phase>test</phase> + <goals> + <goal>report</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> diff --git a/src/main/java/it/inaf/oats/vospace/JobService.java b/src/main/java/it/inaf/oats/vospace/JobService.java new file mode 100644 index 0000000..9e1a59a --- /dev/null +++ b/src/main/java/it/inaf/oats/vospace/JobService.java @@ -0,0 +1,61 @@ +package it.inaf.oats.vospace; + +import it.inaf.oats.vospace.persistence.JobDAO; +import net.ivoa.xml.uws.v1.ExecutionPhase; +import net.ivoa.xml.uws.v1.JobSummary; +import net.ivoa.xml.vospace.v2.Transfer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class JobService { + + @Autowired + private JobDAO jobDAO; + + @Autowired + private UriService uriService; + + @Autowired + private TapeService tapeService; + + enum JobType { + pullToVoSpace, + pullFromVoSpace, + moveNode, + copyNode + } + + public void startJob(JobSummary job) { + + switch (getJobType(job)) { + case pullToVoSpace: + handlePullToVoSpace(job); + break; + case pullFromVoSpace: + handlePullFromVoSpace(job); + break; + default: + throw new UnsupportedOperationException("Not implemented yet"); + } + } + + private void handlePullToVoSpace(JobSummary job) { + // TODO: check protocol + tapeService.startJob(job); + } + + private void handlePullFromVoSpace(JobSummary job) { + job.setPhase(ExecutionPhase.EXECUTING); + uriService.setTransferJobResult(job); + jobDAO.updateJob(job); + } + + private JobType getJobType(JobSummary job) { + + // TODO: check types + Transfer transfer = (Transfer) job.getJobInfo().getAny().get(0); + + return JobType.valueOf(transfer.getDirection()); + } +} diff --git a/src/main/java/it/inaf/oats/vospace/TapeService.java b/src/main/java/it/inaf/oats/vospace/TapeService.java new file mode 100644 index 0000000..42e5c1c --- /dev/null +++ b/src/main/java/it/inaf/oats/vospace/TapeService.java @@ -0,0 +1,35 @@ +package it.inaf.oats.vospace; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.UncheckedIOException; +import net.ivoa.xml.uws.v1.JobSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class TapeService { + + private static final Logger LOG = LoggerFactory.getLogger(TapeService.class); + + @Autowired + private RabbitTemplate template; + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + public JobSummary startJob(JobSummary job) { + try { + byte[] message = MAPPER.writeValueAsBytes(job); + byte[] result = (byte[]) template.convertSendAndReceive("start_job_queue", message); + + LOG.trace("Tape transfer service answered:\n{}", new String(result)); + + return MAPPER.readValue(result, JobSummary.class); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } +} diff --git a/src/main/java/it/inaf/oats/vospace/TransferController.java b/src/main/java/it/inaf/oats/vospace/TransferController.java index 1618fed..f30583f 100644 --- a/src/main/java/it/inaf/oats/vospace/TransferController.java +++ b/src/main/java/it/inaf/oats/vospace/TransferController.java @@ -2,6 +2,7 @@ package it.inaf.oats.vospace; import it.inaf.ia2.aa.data.User; import it.inaf.oats.vospace.persistence.JobDAO; +import java.util.Optional; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import net.ivoa.xml.uws.v1.ExecutionPhase; @@ -29,12 +30,13 @@ public class TransferController { private HttpServletRequest request; @Autowired - private UriService uriService; + private JobService jobService; @PostMapping(value = "/transfers", - consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}, - produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) - public ResponseEntity<?> postTransfer(@RequestBody Transfer transfer, User principal) { + 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, + @RequestParam(value = "PHASE", required = false) Optional<String> phase, User principal) { String jobId = UUID.randomUUID().toString().replace("-", ""); @@ -48,10 +50,14 @@ public class TransferController { jobDAO.createJob(jobSummary); + if (phase.isPresent() && "RUN".equals(phase.get())) { + jobService.startJob(jobSummary); + } + return getJobRedirect(jobId); } - @GetMapping(value = "/transfers/{jobId}", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) + @GetMapping(value = "/transfers/{jobId}", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<JobSummary> getJob(@PathVariable("jobId") String jobId) { return jobDAO.getJob(jobId).map(j -> ResponseEntity.ok(j)).orElse(ResponseEntity.notFound().build()); } @@ -67,9 +73,7 @@ public class TransferController { // TODO: check allowed job phase transitions switch (phase) { case "RUN": - job.setPhase(ExecutionPhase.EXECUTING); - uriService.setTransferJobResult(job); - jobDAO.updateJob(job); + jobService.startJob(job); break; case "ABORT": throw new UnsupportedOperationException("Not implemented yet"); diff --git a/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java b/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java index d8f4018..d87e1f6 100644 --- a/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java +++ b/src/test/java/it/inaf/oats/vospace/TransferControllerTest.java @@ -30,7 +30,7 @@ public class TransferControllerTest { @Autowired private MockMvc mockMvc; - + @Test public void testGetJob() throws Exception { -- GitLab