Commit fb0bb97e authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Implemented basic recall from tape

parent 314c77a3
Loading
Loading
Loading
Loading
+32 −3
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import it.inaf.ia2.vospace.ui.VOSpaceException;
import it.inaf.ia2.vospace.ui.VOSpaceUiApplication;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UncheckedIOException;
import java.net.ConnectException;
import java.net.URI;
@@ -20,7 +21,9 @@ import java.util.function.Function;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXB;
import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Transfer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -42,7 +45,7 @@ public class VOSpaceClient {
    private final ForkJoinPool jaxbExecutor;

    @Autowired
    private HttpServletRequest servletRequest;
    protected HttpServletRequest servletRequest;

    public VOSpaceClient(@Value("${vospace-backend-url}") String backendUrl) {
        if (backendUrl.endsWith("/")) {
@@ -65,7 +68,18 @@ public class VOSpaceClient {
                .header("Accept", useJson ? "application/json" : "text/xml")
                .build();

        return call(request, BodyHandlers.ofInputStream(), 200, res -> parseJson(res, Node.class));
        return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Node.class));
    }

    public JobSummary startTransferJob(Transfer transfer) {

        HttpRequest request = getRequest("/transfers?PHASE=RUN")
                .header("Accept", useJson ? "application/json" : "text/xml")
                .header("Content-Type", useJson ? "application/json" : "text/xml")
                .POST(HttpRequest.BodyPublishers.ofString(marshal(transfer)))
                .build();

        return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, JobSummary.class));
    }

    private <T, U> U call(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, int expectedStatusCode, Function<T, U> responseHandler) {
@@ -116,7 +130,7 @@ public class VOSpaceClient {
        return null;
    }

    private <T> T parseJson(InputStream in, Class<T> type) {
    private <T> T unmarshal(InputStream in, Class<T> type) {
        try {
            if (useJson) {
                return MAPPER.readValue(in, type);
@@ -129,6 +143,21 @@ public class VOSpaceClient {
        }
    }

    private String marshal(Object data) {
        try {
            if (useJson) {
                return MAPPER.writeValueAsString(data);
            } else {
                try ( StringWriter sw = new StringWriter()) {
                    JAXB.marshal(data, sw);
                    return sw.toString();
                }
            }
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }

    private static <T> void logServerError(HttpRequest request, HttpResponse<T> response) {
        if (response.body() instanceof String) {
            logServerErrorString(request, (HttpResponse<String>) response);
+57 −0
Original line number Diff line number Diff line
package it.inaf.ia2.vospace.ui.controller;

import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
import it.inaf.ia2.vospace.ui.data.Job;
import java.util.ArrayList;
import java.util.List;
import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;
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;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JobController {

    @Value("${vospace-authority}")
    private String authority;

    @Autowired
    private VOSpaceClient client;

    @PostMapping(value = "/recall", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Job> startRecallFromTapeJob(@RequestBody List<String> paths) {

        if (paths.size() != 1) {
            throw new UnsupportedOperationException();
        }

        Transfer transfer = new Transfer();
        transfer.setDirection("pullToVoSpace");
        transfer.setTarget("vos://" + authority + paths.get(0));
        Protocol protocol = new Protocol();
        protocol.setUri("ia2:tape-recall");
        transfer.getProtocol().add(protocol);

        JobSummary job = client.startTransferJob(transfer);

        if (job.getPhase() == ExecutionPhase.QUEUED) {
            return ResponseEntity.ok(new Job(job));
        }
        // TODO: proper handling
        throw new RuntimeException("Error while executing job " + job.getJobId() + ". Job phase is " + job.getPhase() + ". QUEUED expected");
    }

    @GetMapping(value = "/jobs", produces = MediaType.APPLICATION_JSON_VALUE)
    public List<Job> getJobs() {
        // TODO
        return new ArrayList<>();
    }
}
+43 −0
Original line number Diff line number Diff line
package it.inaf.ia2.vospace.ui.data;

import net.ivoa.xml.uws.v1.ExecutionPhase;
import net.ivoa.xml.uws.v1.JobSummary;

public class Job {

    private String id;
    private ExecutionPhase phase;
    private boolean read;

    public Job() {
    }

    public Job(JobSummary job) {
        this.id = job.getJobId();
        this.phase = job.getPhase();
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public ExecutionPhase getPhase() {
        return phase;
    }

    public void setPhase(ExecutionPhase phase) {
        this.phase = phase;
    }

    public boolean isRead() {
        return read;
    }

    public void setRead(boolean read) {
        this.read = read;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -85,6 +85,6 @@ public class NodesService {
            return true;
        }
        // TODO: check user group
        return false;
        return true; // temporary always true
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -2,8 +2,10 @@ server.port=8085

vospace-backend-url=http://localhost:8083/vospace
vospace-authority=example.com!vospace
use-json=true
use-json=false

# For development only:
spring.profiles.active=dev
cors.allowed.origin=http://localhost:8080

logging.level.it.inaf=TRACE
Loading