commit
5dbd1e4179
7 changed files with 95 additions and 49 deletions
|
|
@ -39,7 +39,7 @@ func compress(fileToWrite *os.File, folderPath string, backupName string){
|
|||
zr, _ := gzip.NewWriterLevel(fileToWrite, flate.BestCompression)
|
||||
tw := tar.NewWriter(zr)
|
||||
|
||||
go fmt.Printf("[%s] Start compression...\n", filepath.Base(folderPath))
|
||||
go fmt.Printf("[%s] Start compression...\n", backupName)
|
||||
SQL.NewLogEntry(SQL.GetSQLInstance(), uuid.New(), SQL.LogInfo, backupName, SQL.SQLStage_Compress, SQL.REMOTE_NONE, "Start compression", time.Now())
|
||||
filepath.Walk(folderPath, func(file string, fi os.FileInfo, err error) error {
|
||||
header, err := tar.FileInfoHeader(fi, file)
|
||||
|
|
@ -60,7 +60,7 @@ func compress(fileToWrite *os.File, folderPath string, backupName string){
|
|||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
go fmt.Printf("[%s] Compressing: %s (%d bytes)\n", filepath.Base(folderPath) ,relPath, fi.Size())
|
||||
go fmt.Printf("[%s] Compressing: %s (%d bytes)\n", backupName, relPath, fi.Size())
|
||||
if _, err := io.Copy(tw, data); err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
|
@ -78,6 +78,6 @@ func compress(fileToWrite *os.File, folderPath string, backupName string){
|
|||
}
|
||||
|
||||
|
||||
go fmt.Printf("[%s] Compression Done.\n", filepath.Base(folderPath))
|
||||
go fmt.Printf("[%s] Compression Done.\n", backupName)
|
||||
SQL.NewLogEntry(SQL.GetSQLInstance(), uuid.New(), SQL.LogInfo, backupName, SQL.SQLStage_Compress, SQL.REMOTE_NONE, "Compression complete.", time.Now())
|
||||
}
|
||||
14
README.md
14
README.md
|
|
@ -9,6 +9,10 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
|
|||
- Log the Backup progress to a database
|
||||
- Upload the files to a remote storage of your choice (see [Storage Types](#storage-types))
|
||||
|
||||
## Planned features for the Future!
|
||||
- Backup restore
|
||||
- Service for scheduled updates
|
||||
- (Maybe) a web interface
|
||||
|
||||
## Database Types
|
||||
- MariaDB
|
||||
|
|
@ -21,9 +25,9 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
|
|||
|
||||
|
||||
## Storage types
|
||||
- Local storage (soon)
|
||||
- Azure Blob Storage (planned)
|
||||
- Local storage
|
||||
- Azure File Share
|
||||
- Azure Blob Storage (planned)
|
||||
- S3 Bucket (far future)
|
||||
- Dropbox (far future)
|
||||
- OneDrive (far future)
|
||||
|
|
@ -32,13 +36,14 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
|
|||
| Storage Type | Config Type |
|
||||
|-------------------------|--------------------------|
|
||||
| Azure File Share | azure-fileshare |
|
||||
| Local Storage | none |
|
||||
|
||||
|
||||
## Config Explaination
|
||||
|
||||
### config.json
|
||||
| Field | Type | Description |
|
||||
|---------------------|:----------------:|------------------------------------------------|
|
||||
|---------------------------|:----------------:|------------------------------------------------|
|
||||
| localBackupPath | string | Path where local backups are stored |
|
||||
| **sqlConfig** | ---------------- | ---------------------------------------------- |
|
||||
| enableSQL | boolean | Enable/Disables the SQL entries
|
||||
|
|
@ -51,5 +56,6 @@ Trello board: [Click me!](https://trello.com/b/6zWLE6Jm)
|
|||
| **foldersToBackup** | ---------------- | ---------------------------------------------- |
|
||||
| backupName | string | .bak file name |
|
||||
| folderPath | string | Path to folder which should be backed up |
|
||||
| storageType | string | See [StorageTypes](#storage-types) |
|
||||
| remoteStorageType | string | See [StorageTypes](#storage-types) |
|
||||
| targetPath | string | Sets the targetPath for local backups |
|
||||
| createLocalBackup | boolean | Sets if .bak file should also be saved locally |
|
||||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"database/sql"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/google/uuid"
|
||||
"os"
|
||||
"scabiosa/Logging"
|
||||
"scabiosa/Tools"
|
||||
"strconv"
|
||||
|
|
@ -30,7 +31,6 @@ func GetMariaDBInstance(config Tools.Config) MariaDBConnector {
|
|||
return mariadb
|
||||
}
|
||||
|
||||
|
||||
func checkIfEventLogTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
|
||||
rows, _ := db.Query("SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_NAME = 'EventLog';", mariadb.Database)
|
||||
if !rows.Next(){ return false }
|
||||
|
|
@ -43,8 +43,8 @@ func checkIfBackupTableExist(db *sql.DB, mariadb MariaDBConnector) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func checkIfBackupEntryExist(db *sql.DB, mariadb MariaDBConnector, backupName string) bool {
|
||||
rows, _ := db.Query("SELECT * FROM `" + mariadb.Database + "`.Backups WHERE BackupName = '" + backupName + "';")
|
||||
func checkIfBackupEntryExist(db *sql.DB, mariadb MariaDBConnector, backupName string, hostname string) bool {
|
||||
rows, _ := db.Query("SELECT * FROM `" + mariadb.Database + "`.Backups WHERE Hostname = ? AND BackupName = ?;", hostname, backupName)
|
||||
if !rows.Next(){ return false; }
|
||||
return true
|
||||
}
|
||||
|
|
@ -61,9 +61,8 @@ func createMariaDBConnection(mariadb MariaDBConnector) *sql.DB{
|
|||
func (mariadb MariaDBConnector) createDefaultTables(){
|
||||
logger := Logging.DetailedLogger("MariaDB", "createDefaultTables")
|
||||
|
||||
eventLogSQL := "create table " + mariadb.Database +".EventLog\n(\n UUID text null,\n LogType enum ('INFO', 'WARNING', 'ERROR', 'FATAL') null,\n BackupName varchar(256) null,\n Stage enum ('COMPRESS', 'UPLOAD', 'DELETE TMP') null,\n RemoteStorage enum ('AZURE-FILE', 'AZURE-BLOB', 'NONE') null,\n Description text null,\n Timestamp datetime null\n);"
|
||||
backupSQL := "create table " + mariadb.Database +".Backups\n(\n UUID text null,\n BackupName varchar(256) null,\n LastBackup datetime null,\n LocalBackup tinyint(1) null,\n FilePath varchar(256) null,\n RemoteStorage enum ('AZURE-FILE', 'AZURE-BLOB', 'NONE') null,\n RemotePath varchar(256) null\n);\n\n"
|
||||
|
||||
eventLogSQL := "create table `" + mariadb.Database +"`.EventLog(UUID text null, LogType enum ('INFO', 'WARNING', 'ERROR', 'FATAL') null, Hostname varchar(256) null,BackupName varchar(256) null, Stage enum ('COMPRESS', 'UPLOAD', 'DELETE TMP') null, RemoteStorage enum ('AZURE-FILE', 'AZURE-BLOB', 'NONE') null, Description text null, Timestamp datetime null);"
|
||||
backupSQL := "create table `" + mariadb.Database +"`.Backups(UUID text null, Hostname varchar(256) null, BackupName varchar(256) null, LastBackup datetime null, LocalBackup tinyint(1) null, FilePath varchar(256) null, RemoteStorage enum ('AZURE-FILE', 'AZURE-BLOB', 'NONE') null, RemotePath varchar(256) null, LocalPath varchar(256) null);"
|
||||
|
||||
db := createMariaDBConnection(mariadb)
|
||||
|
||||
|
|
@ -88,26 +87,28 @@ func (mariadb MariaDBConnector) newLogEntry(uuid uuid.UUID, logType LogType, bac
|
|||
logger := Logging.DetailedLogger("MariaDB", "newLogEntry")
|
||||
db := createMariaDBConnection(mariadb)
|
||||
|
||||
_, err := db.Query("INSERT INTO `" + mariadb.Database + "`.EventLog VALUES (?, ?, ?, ?, ?, ?, ?);", uuid.String(), strconv.FormatInt(int64(logType), 10), backupName, stage, strconv.FormatInt(int64(storageType), 10), description ,timestamp)
|
||||
hostname, _ := os.Hostname()
|
||||
|
||||
_, err := db.Query("INSERT INTO `" + mariadb.Database + "`.EventLog VALUES (?, ?, ?, ?, ?, ?, ?, ?);", uuid.String(), strconv.FormatInt(int64(logType), 10), hostname, backupName, stage, strconv.FormatInt(int64(storageType), 10), description ,timestamp)
|
||||
if err != nil{
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func (mariadb MariaDBConnector) newBackupEntry(backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string){
|
||||
func (mariadb MariaDBConnector) newBackupEntry(backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string, localPath string){
|
||||
logger := Logging.DetailedLogger("MariaDB", "newBackupEntry")
|
||||
|
||||
db := createMariaDBConnection(mariadb)
|
||||
|
||||
if checkIfBackupEntryExist(db, mariadb, backupName){
|
||||
_, err := db.Query("UPDATE `" + mariadb.Database + "`.Backups SET LastBackup = ? WHERE BackupName = ?;", lastBackup, backupName)
|
||||
hostname, _ := os.Hostname()
|
||||
|
||||
if checkIfBackupEntryExist(db, mariadb, backupName, hostname){
|
||||
_, err := db.Query("UPDATE `" + mariadb.Database + "`.Backups SET LastBackup = ?, LocalBackup = ?, RemoteStorage = ?, RemotePath = ?, LocalPath = ? WHERE Hostname = ? AND BackupName = ?;",lastBackup, localBackup, strconv.FormatInt(int64(storageType), 10), remotePath, localPath, hostname, backupName)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
_, err := db.Query("INSERT INTO `" + mariadb.Database + "`.Backups VALUES (?, ?, ?, ?, ?, ?, ?);", uuid.New(), backupName, lastBackup, localBackup, filePath, strconv.FormatInt(int64(storageType), 10), remotePath)
|
||||
_, err := db.Query("INSERT INTO `" + mariadb.Database + "`.Backups VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);", uuid.New(), hostname, backupName, lastBackup, localBackup, filePath, strconv.FormatInt(int64(storageType), 10), remotePath, localPath)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
type SQLService interface {
|
||||
createDefaultTables()
|
||||
newLogEntry(uuid uuid.UUID, logType LogType, backupName string, stage SQLStage, storageType RemoteStorageType, description string, timestamp time.Time)
|
||||
newBackupEntry(backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string)
|
||||
newBackupEntry(backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string, localPath string)
|
||||
}
|
||||
|
||||
func CreateDefaultTables(sqlService SQLService){
|
||||
|
|
@ -26,10 +26,10 @@ func NewLogEntry(sqlService SQLService, uuid uuid.UUID, logType LogType, backupN
|
|||
}
|
||||
}
|
||||
|
||||
func NewBackupEntry(sqlService SQLService, backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string){
|
||||
func NewBackupEntry(sqlService SQLService, backupName string, lastBackup time.Time, localBackup bool, filePath string, storageType RemoteStorageType, remotePath string, localPath string){
|
||||
config := Tools.GetConfig()
|
||||
if config.SQLConfig.EnableSQL{
|
||||
sqlService.newBackupEntry(backupName, lastBackup, localBackup, filePath, storageType, remotePath)
|
||||
sqlService.newBackupEntry(backupName, lastBackup, localBackup, filePath, storageType, remotePath, localPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@ type Config struct {
|
|||
BackupName string `json:"backupName"`
|
||||
FolderPath string `json:"folderPath"`
|
||||
RemoteStorageType string `json:"remoteStorageType"`
|
||||
TargetPath string `json:"targetPath"`
|
||||
RemoteTargetPath string `json:"remoteTargetPath"`
|
||||
CreateLocalBackup bool `json:"createLocalBackup"`
|
||||
LocalTargetPath string `json:"LocalTargetPath"`
|
||||
} `json:"foldersToBackup"`
|
||||
}
|
||||
|
||||
|
|
@ -36,9 +37,40 @@ func readConfig() []byte {
|
|||
return file
|
||||
}
|
||||
|
||||
func CheckIfConfigExists(){
|
||||
logger := Logging.DetailedLogger("ConfigHandler", "CheckIfConfigExists")
|
||||
|
||||
if _, err := os.Stat("config/config.json"); os.IsNotExist(err){
|
||||
_, fileErr := os.OpenFile("config/config.json", os.O_CREATE, 0775)
|
||||
if fileErr != nil{
|
||||
logger.Fatal(fileErr)
|
||||
}
|
||||
generateDefaultConfig()
|
||||
}
|
||||
}
|
||||
|
||||
func generateDefaultConfig() {
|
||||
logger := Logging.DetailedLogger("ConfigHandler", "GenerateDefaultConfig")
|
||||
|
||||
var config Config
|
||||
var conf []byte
|
||||
|
||||
conf, err := json.MarshalIndent(config, "", "\t")
|
||||
//conf, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.WriteFile("config/config.json", conf, 0755)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetConfig() Config {
|
||||
logger := Logging.DetailedLogger("ConfigHandler", "GetConfig()")
|
||||
|
||||
logger := Logging.DetailedLogger("ConfigHandler", "GetConfig")
|
||||
var config Config
|
||||
|
||||
err := json.Unmarshal(readConfig(), &config)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@
|
|||
{
|
||||
"backupName": "",
|
||||
"folderPath": "",
|
||||
"storageType": "",
|
||||
"targetPath": "",
|
||||
"createLocalBackup": false
|
||||
"remoteStorageType": "",
|
||||
"remoteTargetPath": "",
|
||||
"createLocalBackup": false,
|
||||
"localTargetPath": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
14
main.go
14
main.go
|
|
@ -12,6 +12,7 @@ import (
|
|||
)
|
||||
|
||||
func main(){
|
||||
Tools.CheckIfConfigExists()
|
||||
config := Tools.GetConfig()
|
||||
|
||||
SQL.CreateDefaultTables(SQL.GetSQLInstance())
|
||||
|
|
@ -23,22 +24,27 @@ func main(){
|
|||
|
||||
if backupItem.RemoteStorageType != "none"{
|
||||
storage = StorageTypes.CheckStorageType(backupItem.RemoteStorageType)
|
||||
destPath = checkTmpPath(backupItem.CreateLocalBackup, backupItem.TargetPath)
|
||||
destPath = checkTmpPath(backupItem.CreateLocalBackup, backupItem.LocalTargetPath)
|
||||
} else {
|
||||
destPath = backupItem.TargetPath
|
||||
destPath = backupItem.LocalTargetPath
|
||||
}
|
||||
|
||||
bakFile := Compressor.CreateBakFile(backupItem.BackupName + getTimeSuffix(), backupItem.FolderPath, destPath, backupItem.BackupName)
|
||||
|
||||
if backupItem.RemoteStorageType != "none"{
|
||||
StorageTypes.UploadFile(storage, bakFile, backupItem.BackupName, backupItem.TargetPath)
|
||||
StorageTypes.UploadFile(storage, bakFile, backupItem.BackupName, backupItem.RemoteTargetPath)
|
||||
}
|
||||
|
||||
if !backupItem.CreateLocalBackup && backupItem.RemoteStorageType != "none"{
|
||||
_ = os.Remove(bakFile)
|
||||
SQL.NewLogEntry(SQL.GetSQLInstance(), uuid.New(), SQL.LogInfo, backupItem.BackupName, SQL.SQLStage_DeleteTmp, SQL.REMOTE_NONE, "Deleted tmp file" ,time.Now())
|
||||
}
|
||||
SQL.NewBackupEntry(SQL.GetSQLInstance(), backupItem.BackupName, time.Now(), backupItem.CreateLocalBackup, backupItem.FolderPath, StorageTypes.CheckRemoteStorageType(backupItem.RemoteStorageType), StorageTypes.GetAzureStorage().TargetDirectory)
|
||||
|
||||
if backupItem.RemoteStorageType == "none" {
|
||||
backupItem.CreateLocalBackup = true
|
||||
backupItem.RemoteTargetPath = "NONE"
|
||||
}
|
||||
SQL.NewBackupEntry(SQL.GetSQLInstance(), backupItem.BackupName, time.Now(), backupItem.CreateLocalBackup, backupItem.FolderPath, StorageTypes.CheckRemoteStorageType(backupItem.RemoteStorageType), backupItem.RemoteTargetPath, backupItem.LocalTargetPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue