refactor how the schedule backup works

This commit is contained in:
Usman Nasir
2020-09-20 19:52:02 +05:00
parent 5c00fa909c
commit 9ed61ffb59
4 changed files with 451 additions and 463 deletions

View File

@@ -10,7 +10,7 @@ django.setup()
import json import json
from plogical.acl import ACLManager from plogical.acl import ACLManager
import plogical.CyberCPLogFileWriter as logging import plogical.CyberCPLogFileWriter as logging
from websiteFunctions.models import Websites, Backups, dest, backupSchedules, BackupJob, BackupJobLogs, GDrive, GDriveSites, GDriveJobLogs from websiteFunctions.models import Websites, Backups, dest, backupSchedules, BackupJob, GDrive, GDriveSites
from plogical.virtualHostUtilities import virtualHostUtilities from plogical.virtualHostUtilities import virtualHostUtilities
import subprocess import subprocess
import shlex import shlex
@@ -26,6 +26,7 @@ import requests
import google.oauth2.credentials import google.oauth2.credentials
import googleapiclient.discovery import googleapiclient.discovery
from googleapiclient.discovery import build from googleapiclient.discovery import build
from websiteFunctions.models import NormalBackupDests
class BackupManager: class BackupManager:
@@ -710,35 +711,23 @@ class BackupManager:
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0: if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('destStatus', 0) return ACLManager.loadErrorJson('destStatus', 0)
destinations = backupUtil.backupUtilities.destinationsPath
finalDic = {} finalDic = {}
finalDic['ipAddress'] = data['IPAddress'] if data['type'] == 'SFTP':
finalDic['password'] = data['password']
try: finalDic['ipAddress'] = data['IPAddress']
finalDic['port'] = data['backupSSHPort'] finalDic['password'] = data['password']
except:
finalDic['port'] = "22"
try: try:
finalDic['user'] = data['user'] finalDic['port'] = data['backupSSHPort']
except: except:
finalDic['user'] = "root" finalDic['port'] = "22"
if dest.objects.all().count() == 2: try:
final_dic = {'destStatus': 0, finalDic['user'] = data['user']
'error_message': "Currently only one remote destination is allowed."} except:
final_json = json.dumps(final_dic) finalDic['user'] = "root"
return HttpResponse(final_json)
try:
d = dest.objects.get(destLoc=finalDic['password'])
final_dic = {'destStatus': 0, 'error_message': "This destination already exists."}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except:
execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/backupUtilities.py" execPath = "/usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/backupUtilities.py"
execPath = execPath + " submitDestinationCreation --ipAddress " + finalDic['ipAddress'] + " --password " \ execPath = execPath + " submitDestinationCreation --ipAddress " + finalDic['ipAddress'] + " --password " \
@@ -753,56 +742,63 @@ class BackupManager:
logging.CyberCPLogFileWriter.writeToFile(output) logging.CyberCPLogFileWriter.writeToFile(output)
if output.find('1,') > -1: if output.find('1,') > -1:
try:
writeToFile = open(destinations, "w")
writeToFile.write(json.dumps(finalDic))
writeToFile.close()
newDest = dest(destLoc=finalDic['ipAddress'])
newDest.save()
final_dic = {'destStatus': 1, 'error_message': "None"} config = {'type': data['type'], 'ip': data['IPAddress'], 'username': data['userName'], 'port': data['backupSSHPort'], 'path': data['path']}
final_json = json.dumps(final_dic) nd = NormalBackupDests(name=data['name'], config = json.dumps(config))
return HttpResponse(final_json) nd.save()
except:
writeToFile = open(destinations, "w")
writeToFile.write(json.dumps(finalDic))
writeToFile.close()
newDest = dest(destLoc=finalDic['ipAddress'])
newDest.save()
final_dic = {'destStatus': 1, 'error_message': "None"} final_dic = {'status' : 1, 'destStatus': 1, 'error_message': "None"}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
else:
final_dic = {'destStatus': 0, 'error_message': output}
final_json = json.dumps(final_dic) final_json = json.dumps(final_dic)
return HttpResponse(final_json) return HttpResponse(final_json)
else:
final_dic = {'status' : 0, 'destStatus': 0, 'error_message': output}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
else:
config = {'type': data['type'], 'path': data['path']}
nd = NormalBackupDests(name='local', config=json.dumps(config))
nd.save()
final_dic = {'status' : 1, 'destStatus': 1, 'error_message': "None"}
final_json = json.dumps(final_dic)
return HttpResponse(final_json)
except BaseException as msg: except BaseException as msg:
final_dic = {'destStatus': 0, 'error_message': str(msg)} final_dic = {'status' : 0, 'destStatus': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic) final_json = json.dumps(final_dic)
return HttpResponse(final_json) return HttpResponse(final_json)
def getCurrentBackupDestinations(self, userID=None, data=None): def getCurrentBackupDestinations(self, userID=None, data=None):
try: try:
currentACL = ACLManager.loadedACL(userID) currentACL = ACLManager.loadedACL(userID)
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0: if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('fetchStatus', 0) return ACLManager.loadErrorJson('fetchStatus', 0)
records = dest.objects.all() destinations = NormalBackupDests.objects.all()
json_data = "[" json_data = "["
checker = 0 checker = 0
for items in records: for items in destinations:
if items.destLoc == "Home":
continue config = json.loads(items.config)
dic = {'id': items.id,
'ip': items.destLoc, if config['type'] == data['type'] and data['type'] == 'SFTP':
} dic = {
'name': items.name,
'ip': config['ip'],
'username': config['username'],
'path': config['path'],
'port': config['port'],
}
else:
dic = {
'name': items.name,
'path': config['path'],
}
if checker == 0: if checker == 0:
json_data = json_data + json.dumps(dic) json_data = json_data + json.dumps(dic)
@@ -811,11 +807,11 @@ class BackupManager:
json_data = json_data + ',' + json.dumps(dic) json_data = json_data + ',' + json.dumps(dic)
json_data = json_data + ']' json_data = json_data + ']'
final_json = json.dumps({'fetchStatus': 1, 'error_message': "None", "data": json_data}) final_json = json.dumps({'status': 1, 'error_message': "None", "data": json_data})
return HttpResponse(final_json) return HttpResponse(final_json)
except BaseException as msg: except BaseException as msg:
final_dic = {'fetchStatus': 0, 'error_message': str(msg)} final_dic = {'status': 0, 'error_message': str(msg)}
final_json = json.dumps(final_dic) final_json = json.dumps(final_dic)
return HttpResponse(final_json) return HttpResponse(final_json)
@@ -855,48 +851,25 @@ class BackupManager:
if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0: if ACLManager.currentContextPermission(currentACL, 'addDeleteDestinations') == 0:
return ACLManager.loadErrorJson('delStatus', 0) return ACLManager.loadErrorJson('delStatus', 0)
ipAddress = data['IPAddress'] nameOrPath = data['nameOrPath']
type = data['type']
delDest = dest.objects.get(destLoc=ipAddress) if type == 'SFTP':
delDest.delete() NormalBackupDests.objects.get(name=nameOrPath).delete()
else:
dests = NormalBackupDests.objects.filter(name='local')
for items in dests:
config = json.loads(items.config)
if config['path'] == nameOrPath:
items.delete()
break
path = "/usr/local/CyberCP/backup/" final_dic = {'status': 1, 'delStatus': 1, 'error_message': "None"}
destinations = path + "destinations"
data = open(destinations, 'r').readlines()
writeToFile = open(destinations, 'r')
for items in data:
if items.find(ipAddress) > -1:
continue
else:
writeToFile.writelines(items)
writeToFile.close()
## Deleting Cron Tab Entries for this destination
path = "/etc/crontab"
data = open(path, 'r').readlines()
writeToFile = open(path, 'w')
for items in data:
if items.find("backupSchedule.py") > -1:
continue
else:
writeToFile.writelines(items)
writeToFile.close()
final_dic = {'delStatus': 1, 'error_message': "None"}
final_json = json.dumps(final_dic) final_json = json.dumps(final_dic)
return HttpResponse(final_json) return HttpResponse(final_json)
except BaseException as msg: except BaseException as msg:
final_dic = {'delStatus': 1, 'error_message': str(msg)} final_dic = {'status': 0, 'delStatus': 1, 'error_message': str(msg)}
final_json = json.dumps(final_dic) final_json = json.dumps(final_dic)
return HttpResponse(final_json) return HttpResponse(final_json)

View File

@@ -415,254 +415,6 @@ app.controller('restoreWebsiteControl', function ($scope, $http, $timeout) {
//*** Restore site ends here ***/// //*** Restore site ends here ***///
///** Backup Destination ***//
app.controller('backupDestinations', function ($scope, $http, $timeout) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
populateCurrentRecords();
$scope.addDestination = function () {
$scope.destinationLoading = false;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
url = "/backup/submitDestinationCreation";
var data = {
IPAddress: $scope.IPAddress,
password: $scope.password,
user: $scope.user,
backupSSHPort: $scope.backupSSHPort,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.destStatus == 1) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = false;
$scope.couldNotConnect = true;
populateCurrentRecords();
}
else {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = false;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
$scope.errorMessage = response.data.error_message;
}
}
function cantLoadInitialDatas(response) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = false;
}
};
$scope.checkConn = function (ip) {
$scope.destinationLoading = false;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
url = "/backup/getConnectionStatus";
var data = {
IPAddress: ip,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.connStatus == 1) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = false;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
$scope.IPAddress = ip;
}
else {
$scope.destinationLoading = true;
$scope.connectionFailed = false;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
$scope.errorMessage = response.data.error_message;
$scope.IPAddress = ip;
}
}
function cantLoadInitialDatas(response) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = false;
}
};
$scope.delDest = function (ip) {
$scope.destinationLoading = false;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
url = "/backup/deleteDestination";
var data = {
IPAddress: ip,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.delStatus == 1) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
populateCurrentRecords();
$scope.IPAddress = ip;
}
else {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = true;
$scope.errorMessage = response.data.error_message;
$scope.IPAddress = ip;
}
}
function cantLoadInitialDatas(response) {
$scope.destinationLoading = true;
$scope.connectionFailed = true;
$scope.connectionSuccess = true;
$scope.canNotAddDestination = true;
$scope.destinationAdded = true;
$scope.couldNotConnect = false;
}
};
function populateCurrentRecords() {
url = "/backup/getCurrentBackupDestinations";
var data = {};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.fetchStatus == 1) {
$scope.records = JSON.parse(response.data.data);
}
}
function cantLoadInitialDatas(response) {
$scope.couldNotConnect = false;
}
};
});
//*** Backup destination ***///
///** Schedule Backup ***// ///** Schedule Backup ***//
app.controller('scheduleBackup', function ($scope, $http, $timeout) { app.controller('scheduleBackup', function ($scope, $http, $timeout) {
@@ -1911,3 +1663,191 @@ app.controller('googleDrive', function ($scope, $http) {
}; };
}); });
///
app.controller('backupDestinations', function ($scope, $http) {
$scope.cyberpanelLoading = true;
$scope.sftpHide = true;
$scope.localHide = true;
$scope.fetchDetails = function () {
if ($scope.destinationType === 'SFTP') {
$scope.sftpHide = false;
$scope.localHide = true;
$scope.populateCurrentRecords();
} else {
$scope.sftpHide = true;
$scope.localHide = false;
$scope.populateCurrentRecords();
}
};
$scope.populateCurrentRecords = function () {
$scope.cyberpanelLoading = false;
url = "/backup/getCurrentBackupDestinations";
var type = 'SFTP';
if ($scope.destinationType === 'SFTP') {
type = 'SFTP';
} else {
type = 'local';
}
var data = {
type: type
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
$scope.records = JSON.parse(response.data.data);
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
$scope.addDestination = function (type) {
$scope.cyberpanelLoading = false;
url = "/backup/submitDestinationCreation";
if (type === 'SFTP') {
var data = {
type: type,
name: $scope.name,
IPAddress: $scope.IPAddress,
userName: $scope.userName,
password: $scope.password,
backupSSHPort: $scope.backupSSHPort,
path: $scope.path
};
} else {
var data = {
type: type,
path: $scope.localPath,
};
}
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
$scope.populateCurrentRecords();
if (response.data.status === 1) {
new PNotify({
title: 'Success!',
text: 'Destination successfully added.',
type: 'success'
});
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
$scope.removeDestination = function (type, nameOrPath) {
$scope.cyberpanelLoading = false;
url = "/backup/deleteDestination";
var data = {
type: type,
nameOrPath: nameOrPath,
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
$scope.cyberpanelLoading = true;
$scope.populateCurrentRecords();
if (response.data.status === 1) {
new PNotify({
title: 'Success!',
text: 'Destination successfully removed.',
type: 'success'
});
} else {
new PNotify({
title: 'Operation Failed!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
});

View File

@@ -3,134 +3,202 @@
{% block title %}{% trans "Set up Back up Destinations" %}{% endblock %} {% block title %}{% trans "Set up Back up Destinations" %}{% endblock %}
{% block content %} {% block content %}
{% load static %} {% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Set up Back up Destinations" %} - <a target="_blank" href="http://go.cyberpanel.net/remote-backup" style="height: 23px;line-height: 21px;" class="btn btn-border btn-alt border-red btn-link font-red" title=""><span>{% trans "Remote Backups" %}</span></a></h2>
<p>{% trans "On this page you can set up your Back up destinations. (SFTP)" %}</p>
</div>
<div ng-controller="backupDestinations" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Set up Back up Destinations (SSH port should be 22 on backup server)" %} <img ng-hide="destinationLoading" src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "IP Address" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="IPAddress" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "User" %}</label>
<div class="col-sm-6">
<input placeholder="{% trans "Backup server SSH User, leave empty for root." %}" type="text" class="form-control" ng-model="user" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Password" %}</label>
<div class="col-sm-6">
<input placeholder="" type="password" class="form-control" ng-model="password" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Port" %}</label>
<div class="col-sm-6">
<input placeholder="{% trans "Backup server SSH Port, leave empty for 22." %}" type="text" class="form-control" ng-model="backupSSHPort" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addDestination()" class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!------ List of Destinations --------------->
<div class="form-group">
<div class="col-sm-12">
<div ng-hide="connectionFailed" class="alert alert-danger">
<p>{% trans "Connection to" %} {$ IPAddress $} {% trans "failed. Please delete and re-add. " %} {$ errorMessage $} </p>
</div>
<div ng-hide="connectionSuccess" class="alert alert-success">
<p>{% trans "Connection to" %} {$ IPAddress $} {% trans "successful." %}</p>
</div>
<div ng-hide="canNotAddDestination" class="alert alert-danger">
<p>{% trans "Cannot add destination. Error message:" %} {$ errorMessage $} </p>
</div>
<div ng-hide="destinationAdded" class="alert alert-success">
<p>{% trans "Destination Added." %}</p>
</div>
<div ng-hide="couldNotConnect" class="alert alert-danger">
<p>{% trans "Could not connect to server. Please refresh this page." %}</p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "IP" %}</th>
<th>{% trans "Check Connection" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.id"></td>
<td ng-bind="record.ip"></td>
<td><button type="button" ng-click="checkConn(record.ip)" class="btn ra-100 btn-purple">{% trans "Check Connection" %}</button></td>
<td ng-click="delDest(record.ip)"><img src="{% static 'images/delete.png' %}"></td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
</form>
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Set up Back up Destinations" %} - <a target="_blank"
href="https://go.cyberpanel.net/remote-backup"
style="height: 23px;line-height: 21px;"
class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a>
</h2>
<p>{% trans "On this page you can set up your Back up destinations. (SFTP)" %}</p>
</div> </div>
<div ng-controller="backupDestinations" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Set up Back up Destinations." %} <img ng-hide="cyberpanelLoading"
src="{% static 'images/loading.gif' %}">
</h3>
<div class="example-box-wrapper">
<form action="/" class="form-horizontal bordered-row">
<div class="form-group">
<label class="col-sm-3 control-label">{% trans "Select Type" %} </label>
<div class="col-sm-6">
<select ng-change="fetchDetails()" ng-model="destinationType" class="form-control">
<option>local</option>
<option>SFTP</option>
</select>
</div>
</div>
<!--- SFTP --->
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Name" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="name" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "IP Address" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="IPAddress" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Username" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="userName" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Password" %}</label>
<div class="col-sm-6">
<input placeholder="" type="password" class="form-control" ng-model="password" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Port" %}</label>
<div class="col-sm-6">
<input placeholder="{% trans "Backup server SSH Port, leave empty for 22." %}"
type="text" class="form-control" ng-model="backupSSHPort" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Path" %}</label>
<div class="col-sm-6">
<input placeholder="Path on remote server to store backups." type="text" class="form-control" ng-model="path" required>
</div>
</div>
<div ng-hide="sftpHide" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addDestination('SFTP')"
class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!--- SFTP --->
<!------ List of Destinations --------------->
<div ng-hide="sftpHide" class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "IP" %}</th>
<th>{% trans "Username" %}</th>
<th>{% trans "Path" %}</th>
<th>{% trans "Port" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.name"></td>
<td ng-bind="record.ip"></td>
<td ng-bind="record.username"></td>
<td ng-bind="record.path"></td>
<td ng-bind="record.port"></td>
<td ng-click="removeDestination('SFTP', record.name)"><img src="{% static 'images/delete.png' %}">
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
<!--- SFTP End --->
<!--- AWS Start --->
<div ng-hide="localHide" class="form-group">
<label class="col-sm-3 control-label">{% trans "Local Path" %}</label>
<div class="col-sm-6">
<input type="text" class="form-control" ng-model="localPath" required>
</div>
</div>
<div ng-hide="localHide" class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-4">
<button type="button" ng-click="addDestination('local')"
class="btn btn-primary btn-lg btn-block">{% trans "Add Destination" %}</button>
</div>
</div>
<!--- SFTP --->
<!------ List of Destinations --------------->
<div ng-hide="localHide" class="form-group">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>{% trans "Path" %}</th>
<th>{% trans "Delete" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="record in records track by $index">
<td ng-bind="record.path"></td>
<td ng-click="removeDestination('local', record.path)"><img src="{% static 'images/delete.png' %}">
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!------ List of records --------------->
<!--- AWS End --->
</form>
</div>
</div>
</div>
</div> </div>
</div>
</div>
{% endblock %} {% endblock %}

View File

@@ -75,4 +75,11 @@ class GDriveSites(models.Model):
class GDriveJobLogs(models.Model): class GDriveJobLogs(models.Model):
owner = models.ForeignKey(GDrive, on_delete=models.CASCADE) owner = models.ForeignKey(GDrive, on_delete=models.CASCADE)
status = models.IntegerField() status = models.IntegerField()
message = models.TextField() message = models.TextField()
### Normal backup models
class NormalBackupDests(models.Model):
name = models.CharField(max_length=25)
config = models.TextField()