From 91c24ab5c6bafe0b3f5a83b018ed6feb31cfc225 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Tue, 15 Jan 2019 16:51:38 +0000
Subject: [PATCH] Auto-install borg...

---
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java    |   13 +++
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java       |   67 ++++++++++++++++++---
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java |    4 +
 borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx                   |   39 +++++++++---
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/SystemInfoRest.java    |    4 
 borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java            |    5 +
 6 files changed, 106 insertions(+), 26 deletions(-)

diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
index e76a972..6f4dd5c 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgInstallation.java
@@ -22,8 +22,6 @@
     private Logger log = LoggerFactory.getLogger(BorgInstallation.class);
     private static final BorgInstallation instance = new BorgInstallation();
 
-    private BorgVersion borgVersion = new BorgVersion();
-
     public static BorgInstallation getInstance() {
         return instance;
     }
@@ -35,36 +33,76 @@
                 return;
             }
         }
-        String[] binary = getBinary(RunningMode.getOSType());
-        File file = download(binary);
-        configuration.setBorgCommand(file.getAbsolutePath());
+        initialize(getBinary(RunningMode.getOSType()));
         if (version(configuration)) {
             return;
         }
+        BorgVersion borgVersion = ServerConfiguration.get()._getBorgVersion();
         log.warn("No working borg version found. Please configure a borg version with minimal version '" + borgVersion.getMinimumRequiredBorgVersion() + "'.");
     }
 
     /**
-     * @return a clone of this.borgVersion.
+     * Configures a new borg configuration if modifications was done.
+     * @param oldVersion The old version before this current modification.
      */
-    public BorgVersion getVersion() {
-        return new BorgVersion().copyFrom(borgVersion);
+    public void configure(BorgVersion oldVersion) {
+        Configuration configuration = ConfigurationHandler.getConfiguration();
+        BorgVersion newVersion = ServerConfiguration.get()._getBorgVersion();
+        boolean borgBinaryChanged = !StringUtils.equals(oldVersion.getBorgBinary(), newVersion.getBorgBinary());
+        boolean manualBorgCommand = "manual".equals(newVersion.getBorgBinary());
+        if (manualBorgCommand) {
+            boolean borgCommandChanged = !StringUtils.equals(oldVersion.getBorgCommand(), newVersion.getBorgCommand());
+            if (borgCommandChanged) {
+                configuration.setBorgCommand(newVersion.getBorgCommand());
+                version(configuration);
+            }
+        } else {
+            if (borgBinaryChanged) {
+                newVersion.setBorgCommand(oldVersion.getBorgCommand()); // Don't modify borg command, if not manual.
+                initialize(getBinary(newVersion.getBorgBinary()));
+            } else {
+                newVersion.copyFrom(oldVersion); // Restore all old settings.
+            }
+        }
+    }
+
+    private boolean initialize(String[] binary) {
+        if (binary == null) {
+            return false;
+        }
+        Configuration configuration = ConfigurationHandler.getConfiguration();
+        File file = download(binary);
+        BorgVersion borgVersion = ServerConfiguration.get()._getBorgVersion();
+        if (file != null) {
+            configuration.setBorgCommand(file.getAbsolutePath());
+            borgVersion.setBorgCommand(file.getAbsolutePath());
+            borgVersion.setBorgBinary(binary[0]);
+        }
+        return version(configuration);
     }
 
     private boolean version(Configuration configuration) {
         String versionString = BorgCommands.version();
         boolean versionOK = false;
+        BorgVersion borgVersion = ServerConfiguration.get()._getBorgVersion();
+        String msg = null;
         if (versionString != null) {
+            borgVersion.setVersion(versionString);
             int cmp = versionString.compareTo(borgVersion.getMinimumRequiredBorgVersion());
             if (cmp < 0) {
-                log.info("Found borg version '" + versionString + "' is less than minimum required version '" + borgVersion.getMinimumRequiredBorgVersion() + "'.");
+                msg = "Found borg version '" + versionString + "' is less than minimum required version '" + borgVersion.getMinimumRequiredBorgVersion() + "'.";
+                log.info(msg);
             } else {
                 versionOK = true;
-                log.info("Found borg '" + configuration.getBorgCommand() + "', version: " + versionString + " (equals to or newer than '" + borgVersion.getMinimumRequiredBorgVersion()
-                        + "', OK).");
+                msg = "Found borg '" + configuration.getBorgCommand() + "', version: " + versionString + " (equals to or newer than '" + borgVersion.getMinimumRequiredBorgVersion()
+                        + "', OK).";
+                log.info(msg);
             }
+        } else {
+            msg = "Couldn't execute borg command '" + configuration.getBorgCommand() + "'.";
         }
         borgVersion.setVersionOK(versionOK);
+        borgVersion.setStatusMessage(msg);
         return versionOK;
     }
 
@@ -81,9 +119,14 @@
                 os = "freebsd64";
                 break;
         }
+        return getBinary(os);
+    }
+
+    private String[] getBinary(String os) {
         if (os == null) {
             return null;
         }
+        BorgVersion borgVersion = ServerConfiguration.get()._getBorgVersion();
         for (String[] binary : borgVersion.getBorgBinaries()) {
             if (binary[0].contains(os)) {
                 return binary;
@@ -107,6 +150,7 @@
             // File already downloaded, nothing to do.
             return file;
         }
+        BorgVersion borgVersion = ServerConfiguration.get()._getBorgVersion();
         String url = borgVersion.getBinariesDownloadUrl() + getDownloadFilename(binary);
         log.info("Trying to download borg binary '" + binary[0] + "' (" + binary[1] + ") from url: " + url + "...");
         HttpClientBuilder builder = HttpClients.custom()
@@ -137,6 +181,7 @@
             log.info("Creating binary directory: " + dir.getAbsolutePath());
             dir.mkdirs();
         }
+        BorgVersion borgVersion = ServerConfiguration.get()._getBorgVersion();
         return new File(dir, getDownloadFilename(binary) + "-" + borgVersion.getBinariesDownloadVersion());
     }
 
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java
index 318d0a7..2f856d4 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/BorgVersion.java
@@ -24,6 +24,7 @@
      * using a manual installed borg version.
      */
     @Getter
+    @Setter(AccessLevel.PACKAGE)
     private String borgBinary;
     /**
      * The path of the borg command to use.
@@ -38,12 +39,16 @@
     @Getter
     @Setter(AccessLevel.PACKAGE)
     private String version;
+    @Getter
+    @Setter(AccessLevel.PACKAGE)
+    private String statusMessage;
 
     public BorgVersion copyFrom(BorgVersion other) {
         this.borgCommand = other.borgCommand;
         this.borgBinary = other.borgBinary;
         this.versionOK = other.versionOK;
         this.version = other.version;
+        this.statusMessage = other.statusMessage;
         return this;
     }
 }
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java
index 78dffe1..d3d308f 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/ServerConfiguration.java
@@ -4,7 +4,6 @@
 import de.micromata.borgbutler.cache.ButlerCache;
 import de.micromata.borgbutler.config.Configuration;
 import de.micromata.borgbutler.config.ConfigurationHandler;
-import lombok.Getter;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -19,7 +18,6 @@
 
     private int port = WEBSERVER_PORT_DEFAULT;
     private boolean webDevelopmentMode = WEB_DEVELOPMENT_MODE_PREF_DEFAULT;
-    @Getter
     private BorgVersion borgVersion = new BorgVersion();
     @JsonProperty
     public String getCacheDir() {
@@ -34,6 +32,17 @@
         return SUPPORTED_LANGUAGES;
     }
 
+    /**
+     * @return a clone of this.borgVersion.
+     */
+    public BorgVersion getBorgVersion() {
+        return new BorgVersion().copyFrom(borgVersion);
+    }
+
+    BorgVersion _getBorgVersion() {
+        return this.borgVersion;
+    }
+
     public static String getApplicationHome() {
         if (applicationHome == null) {
             applicationHome = System.getProperty("applicationHome");
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java
index 06abb81..c5fa7b0 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/ConfigurationRest.java
@@ -3,6 +3,8 @@
 import de.micromata.borgbutler.cache.ButlerCache;
 import de.micromata.borgbutler.config.ConfigurationHandler;
 import de.micromata.borgbutler.json.JsonUtils;
+import de.micromata.borgbutler.server.BorgInstallation;
+import de.micromata.borgbutler.server.BorgVersion;
 import de.micromata.borgbutler.server.ServerConfiguration;
 import de.micromata.borgbutler.server.user.UserData;
 import de.micromata.borgbutler.server.user.UserManager;
@@ -37,7 +39,9 @@
         ConfigurationHandler configurationHandler = ConfigurationHandler.getInstance();
         ServerConfiguration config = (ServerConfiguration)configurationHandler.getConfiguration();
         ServerConfiguration srcConfig = JsonUtils.fromJson(ServerConfiguration.class, jsonConfig);
+        BorgVersion oldBorgVersion = config.getBorgVersion();
         config.copyFrom(srcConfig);
+        BorgInstallation.getInstance().configure(oldBorgVersion);
         configurationHandler.save();
     }
 
diff --git a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/SystemInfoRest.java b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/SystemInfoRest.java
index 6077481..3a7b989 100644
--- a/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/SystemInfoRest.java
+++ b/borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/SystemInfoRest.java
@@ -2,8 +2,8 @@
 
 import de.micromata.borgbutler.BorgQueueExecutor;
 import de.micromata.borgbutler.json.JsonUtils;
-import de.micromata.borgbutler.server.BorgInstallation;
 import de.micromata.borgbutler.server.BorgVersion;
+import de.micromata.borgbutler.server.ServerConfiguration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -24,7 +24,7 @@
      * @see JsonUtils#toJson(Object, boolean)
      */
     public String getStatistics() {
-        BorgVersion borgVersion = BorgInstallation.getInstance().getVersion();
+        BorgVersion borgVersion = ServerConfiguration.get().getBorgVersion();
         SystemInfo systemInfonfo = new SystemInfo()
                 .setQueueStatistics(BorgQueueExecutor.getInstance().getStatistics())
                 .setConfigurationOK(borgVersion.isVersionOK())
diff --git a/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx b/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
index ef49de8..2238275 100644
--- a/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
+++ b/borgbutler-webapp/src/components/views/config/ConfigurationServerTab.jsx
@@ -1,5 +1,5 @@
 import React from 'react';
-import {Button} from 'reactstrap';
+import {Alert} from 'reactstrap';
 import {
     FormCheckbox,
     FormField,
@@ -35,6 +35,8 @@
             .then((data) => {
                 this.setState({
                     loading: false,
+                    borgBinary: data.borgVersion.borgBinary,
+                    borgCommand: data.borgVersion.borgCommand,
                     ...data
                 })
             })
@@ -58,7 +60,8 @@
             showDemoRepos: true,
             maxArchiveContentCacheCapacityMb: 100,
             redirect: false,
-            borgVersion: null
+            borgCommand: null,
+            borgBinary: null
         };
 
         this.handleTextChange = this.handleTextChange.bind(this);
@@ -84,7 +87,11 @@
             port: this.state.port,
             maxArchiveContentCacheCapacityMb: this.state.maxArchiveContentCacheCapacityMb,
             webDevelopmentMode: this.state.webDevelopmentMode,
-            showDemoRepos: this.state.showDemoRepos
+            showDemoRepos: this.state.showDemoRepos,
+            borgVersion: {
+                borgCommand: this.state.borgCommand,
+                borgBinary: this.state.borgBinary
+            }
         };
         return fetch(getRestServiceUrl("configuration/config"), {
             method: 'POST',
@@ -114,6 +121,14 @@
             return <ErrorAlertGenericRestFailure handleClick={this.loadConfig}/>;
         }
         const borgVersion = this.state.borgVersion;
+        let borgStatus = <Alert color="success">
+            {`Borg version '${borgVersion.version}' is OK.`}
+        </Alert>
+        if (!borgVersion.versionOK) {
+            borgStatus = <Alert color="danger">
+                {`${borgVersion.statusMessage}`}
+            </Alert>
+        }
         return (
             <div>
                 <form>
@@ -121,8 +136,8 @@
                         <FormLabel>{'Borg command'}</FormLabel>
                         <FormField length={2}>
                             <FormSelect
-                                value={borgVersion.binary}
-                                name={'binary'}
+                                value={this.state.borgBinary}
+                                name={'borgBinary'}
                                 onChange={this.handleTextChange}
                                 hint={`Choose your OS and BorgButler will download and use a ready to run borg binary from ${borgVersion.binariesDownloadUrl} or choose a manual installed version.`}
                             >
@@ -132,15 +147,17 @@
                                 <FormOption label={'Manual'} value={'manual'}/>
                             </FormSelect>
                         </FormField>
-                        <FormField length={6}>
+                        <FormField length={8}>
                             <FormInput name={'borgCommand'} value={this.state.borgCommand}
                                        onChange={this.handleTextChange}
-                                       placeholder="Enter path of borg command"/>
+                                       placeholder="Enter path of borg command"
+                                       disabled={this.state.borgBinary !== "manual"}/>
                         </FormField>
-                        <FormField length={2}>
-                            <Button className={'outline-primary'} onClick={this.onCancel}
-                                    hint={'Tests the borg version.'}>Test
-                            </Button>
+                    </FormGroup>
+                    <FormGroup>
+                        <FormField length={2} />
+                        <FormField length={10}>
+                            {borgStatus}
                         </FormField>
                     </FormGroup>
                     <FormLabelInputField label={'Port'} fieldLength={2} type="number" min={0} max={65535}

--
Gitblit v1.10.0