mirror of https://github.com/micromata/borgbackup-butler.git

...
Kai Reinhard
19.56.2018 b6fa15f5da2312ac580ce329f569fd4b3a826f24
...
3 files modified
177 ■■■■■ changed files
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommand.java 80 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java 45 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgExecutorQueue.java 52 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommand.java
@@ -1,26 +1,84 @@
package de.micromata.borgbutler;
import de.micromata.borgbutler.config.BorgRepoConfig;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import java.io.File;
/**
 * Represents a command to be queued for executing.
 */
public class BorgCommand {
    private Logger log = LoggerFactory.getLogger(BorgCommand.class);
    /**
     * The current Thread assigned to this command sets the state and reads for the state {@link State#TERMINATE_SIGNAL_RECEIVED}.
     * If received, the thread will be terminated without executing the borg command.
     */
    public enum State {
        /**
         * This command is waiting in the queue.
         */
        WAITING_IN_QUEUE,
        /**
         * This command is running (beeing executed).
         */
        RUNNING,
        /**
         * This command should not be terminated before starting.
         */
        TERMINATE_SIGNAL_RECEIVED}
    public enum ResultStatus {
        OK, ERROR
    }
    @Getter
    @Setter
    File workingDir;
    String[] args;
    String[] params;
    private File workingDir;
    @Getter
    private String[] args;
    @Getter
    private String[] params;
    @Getter
    @Setter
    BorgRepoConfig repoConfig;
    private BorgRepoConfig repoConfig;
    @Getter
    @Setter
    String command;
    private String command;
    @Getter
    @Setter
    String archive;
    private String archive;
    @Getter
    private State state;
    /**
     * For displaying and information purposes for the user only, when browsing the current command queue.
     */
    @Setter
    @Getter
    private String description;
    /**
     * The result of the call will be written to this String.
     */
    @Getter
    @Setter(AccessLevel.PACKAGE)
    private String response;
    @Getter
    @Setter(AccessLevel.PACKAGE)
    private ResultStatus resultStatus;
    /**
     * Requests the thread handling this command to terminate / cancel this action.
     */
    public void terminate() {
        this.state = State.TERMINATE_SIGNAL_RECEIVED;
    }
    BorgCommand setArgs(String... args) {
        this.args = args;
@@ -38,4 +96,12 @@
        }
        return repoConfig.getRepo() + "::" + archive;
    }
    /**
     *
     * @return Abbreviated response e. g. for logging an error.
     */
    public String getAbbreviatedResponse() {
        return StringUtils.abbreviate(response, 1000);
    }
}
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
@@ -9,14 +9,12 @@
import de.micromata.borgbutler.utils.DateUtils;
import de.micromata.borgbutler.utils.ReplaceUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
@@ -33,12 +31,12 @@
     * @return Parsed repo config returned by Borg command (without archives).
     */
    public static Repository info(BorgRepoConfig repoConfig) {
        BorgCommand context = new BorgCommand().setRepoConfig(repoConfig).setCommand("info").setParams("--json");
        String json = execute(context);
        if (json == null) {
        BorgCommand command = new BorgCommand().setRepoConfig(repoConfig).setCommand("info").setParams("--json");
        execute(command);
        if (command.getResultStatus() != BorgCommand.ResultStatus.OK) {
            return null;
        }
        BorgRepoInfo repoInfo = JsonUtils.fromJson(BorgRepoInfo.class, json);
        BorgRepoInfo repoInfo = JsonUtils.fromJson(BorgRepoInfo.class, command.getResponse());
        BorgRepository borgRepository = repoInfo.getRepository();
        Repository repository = new Repository()
                .setId(borgRepository.getId())
@@ -62,12 +60,12 @@
     */
    public static void list(BorgRepoConfig repoConfig, Repository repository) {
        BorgCommand command = new BorgCommand().setRepoConfig(repoConfig).setCommand("list").setParams("--json");
        String json = execute(command);
        if (json == null) {
        execute(command);
        if (command.getResultStatus() != BorgCommand.ResultStatus.OK) {
            log.error("Can't load archives from repo '" + repository.getName() + "'.");
            return;
        }
        BorgRepoList repoList = JsonUtils.fromJson(BorgRepoList.class, json);
        BorgRepoList repoList = JsonUtils.fromJson(BorgRepoList.class, command.getResponse());
        if (repoList == null || CollectionUtils.isEmpty(repoList.getArchives())) {
            log.error("Can't load archives from repo '" + repository.getName() + "'.");
            return;
@@ -99,11 +97,11 @@
    public static void info(BorgRepoConfig repoConfig, Archive archive, Repository repository) {
        BorgCommand command = new BorgCommand().setRepoConfig(repoConfig).setCommand("info").setArchive(archive.getName())
                .setParams("--json");
        String json = execute(command);
        if (json == null) {
        execute(command);
        if (command.getResultStatus() != BorgCommand.ResultStatus.OK) {
            return;
        }
        BorgArchiveInfo archiveInfo = JsonUtils.fromJson(BorgArchiveInfo.class, json);
        BorgArchiveInfo archiveInfo = JsonUtils.fromJson(BorgArchiveInfo.class, command.getResponse());
        if (archiveInfo == null) {
            log.error("Archive '" + command.getRepoArchive() + "' not found.");
            return;
@@ -113,7 +111,7 @@
        archive.setCache(archiveInfo.getCache())
                .setEncryption(archiveInfo.getEncryption());
        if (CollectionUtils.isEmpty(archiveInfo.getArchives())) {
            log.error("The returned borg archive contains no archive infos: " + json);
            log.error("The returned borg archive contains no archive infos: " + command.getAbbreviatedResponse());
            return;
        }
        if (archiveInfo.getArchives().size() > 1) {
@@ -136,11 +134,12 @@
    public static List<BorgFilesystemItem> listArchiveContent(BorgRepoConfig repoConfig, String archive) {
        BorgCommand command = new BorgCommand().setRepoConfig(repoConfig).setCommand("list").setArchive(archive)
                .setParams("--json-lines");
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        execute(outputStream, command);
        String response = outputStream.toString(Definitions.STD_CHARSET);
        execute(command);
        List<BorgFilesystemItem> content = new ArrayList<>();
        try (Scanner scanner = new Scanner(response)) {
        if (command.getResultStatus() != BorgCommand.ResultStatus.OK) {
            return content;
        }
        try (Scanner scanner = new Scanner(command.getResponse())) {
            while (scanner.hasNextLine()) {
                String json = scanner.nextLine();
                BorgFilesystemItem item = JsonUtils.fromJson(BorgFilesystemItem.class, json);
@@ -173,15 +172,9 @@
        return restoreDir;
    }
    private static String execute(BorgCommand command) {
    private static void execute(BorgCommand command) {
        Validate.notNull(command);
        Validate.notNull(command.repoConfig);
        return BorgExecutorQueue.getQueue(command.repoConfig).execute(command);
    }
    private static void execute(OutputStream outputStream, BorgCommand command) {
        Validate.notNull(command);
        Validate.notNull(command.repoConfig);
        BorgExecutorQueue.getQueue(command.repoConfig).execute(outputStream, command);
        Validate.notNull(command.getRepoConfig());
        BorgExecutorQueue.getQueue(command.getRepoConfig()).execute(command);
    }
}
borgbutler-core/src/main/java/de/micromata/borgbutler/BorgExecutorQueue.java
@@ -14,7 +14,6 @@
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -41,44 +40,41 @@
    private ConcurrentLinkedQueue<BorgCommand> commandQueue = new ConcurrentLinkedQueue<>();
    public String execute(BorgCommand command) {
    public void execute(BorgCommand command) {
        synchronized (this) {
            return _exceute(command);
            commandQueue.add(command);
            _execute(command);
        }
        /*
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                log.warn("Command '" + command.);
            }
        }*/
    }
    private String _exceute(BorgCommand command) {
    private void _execute(BorgCommand command) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        execute(outputStream, command);
        String json = outputStream.toString(Definitions.STD_CHARSET);
        return json;
    }
    public void execute(OutputStream outputStream, BorgCommand command) {
        synchronized (this) {
            _execute(outputStream, command);
        }
    }
    private void _execute(OutputStream outputStream, BorgCommand command) {
        CommandLine cmdLine = new CommandLine(ConfigurationHandler.getConfiguration().getBorgCommand());
        cmdLine.addArgument(command.command);
        if (command.params != null) {
            for (String param : command.params) {
        cmdLine.addArgument(command.getCommand());
        if (command.getParams() != null) {
            for (String param : command.getParams()) {
                if (param != null)
                    cmdLine.addArgument(param);
            }
        }
        cmdLine.addArgument(command.getRepoArchive());
        if (command.args != null) {
            for (String arg : command.args) {
        if (command.getArgs() != null) {
            for (String arg : command.getArgs()) {
                if (arg != null)
                    cmdLine.addArgument(arg);
            }
        }
        DefaultExecutor executor = new DefaultExecutor();
        if (command.workingDir != null) {
            executor.setWorkingDirectory(command.workingDir);
        if (command.getWorkingDir() != null) {
            executor.setWorkingDirectory(command.getWorkingDir());
        }
        //executor.setExitValue(2);
        //ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
@@ -89,12 +85,16 @@
        String borgCall = cmdLine.getExecutable() + " " + StringUtils.join(cmdLine.getArguments(), " ");
        log.info("Executing '" + borgCall + "'...");
        try {
            executor.execute(cmdLine, getEnvironment(command.repoConfig));
            executor.execute(cmdLine, getEnvironment(command.getRepoConfig()));
        } catch (Exception ex) {
            log.error("Error while creating environment for borg call '" + borgCall + "': " + ex.getMessage(), ex);
            log.error("Response: " + StringUtils.abbreviate(outputStream.toString(), 10000));
            return;
            command.setResultStatus(BorgCommand.ResultStatus.ERROR);
        }
        command.setResponse(outputStream.toString(Definitions.STD_CHARSET));
        if (command.getResultStatus() == BorgCommand.ResultStatus.ERROR) {
            log.error("Response: " + command.getAbbreviatedResponse());
        }
    }