add detailed schedule backup logging

This commit is contained in:
Usman Nasir
2020-05-21 23:21:36 +05:00
parent 12a5401775
commit b489689a76
10 changed files with 413 additions and 21 deletions

View File

@@ -9,7 +9,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 from websiteFunctions.models import Websites, Backups, dest, backupSchedules, BackupJob, BackupJobLogs
from plogical.virtualHostUtilities import virtualHostUtilities from plogical.virtualHostUtilities import virtualHostUtilities
import subprocess import subprocess
import shlex import shlex
@@ -1186,3 +1186,96 @@ class BackupManager:
data = {'cancelStatus': 0, 'error_message': str(msg)} data = {'cancelStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(data) json_data = json.dumps(data)
return HttpResponse(json_data) return HttpResponse(json_data)
def backupLogs(self, request = None, userID = None, data = None):
try:
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadError()
all_files = []
logFiles = BackupJob.objects.all().order_by('-id')
for logFile in logFiles:
all_files.append(logFile.logFile)
return render(request, 'backup/backupLogs.html', {'backups': all_files})
except BaseException as msg:
return HttpResponse(str(msg))
def fetchLogs(self, userID = None, data = None):
try:
currentACL = ACLManager.loadedACL(userID)
if currentACL['admin'] == 1:
pass
else:
return ACLManager.loadError()
page = int(str(data['page']).rstrip('\n'))
recordsToShow = int(data['recordsToShow'])
logFile = data['logFile']
logJob = BackupJob.objects.get(logFile=logFile)
logs = logJob.backupjoblogs_set.all()
from s3Backups.s3Backups import S3Backups
from plogical.backupSchedule import backupSchedule
pagination = S3Backups.getPagination(len(logs), recordsToShow)
endPageNumber, finalPageNumber = S3Backups.recordsPointer(page, recordsToShow)
finalLogs = logs[finalPageNumber:endPageNumber]
json_data = "["
checker = 0
counter = 0
for log in finalLogs:
if log.status == backupSchedule.INFO:
status = 'INFO'
else:
status = 'ERROR'
dic = {
'LEVEL': status, "Message": log.message
}
if checker == 0:
json_data = json_data + json.dumps(dic)
checker = 1
else:
json_data = json_data + ',' + json.dumps(dic)
counter = counter + 1
json_data = json_data + ']'
if logJob.location == backupSchedule.LOCAL:
location = 'local'
else:
location = 'remote'
data = {
'status': 1,
'error_message': 'None',
'logs': json_data,
'pagination': pagination,
'jobSuccessSites': logJob.jobSuccessSites,
'jobFailedSites': logJob.jobFailedSites,
'location': location
}
json_data = json.dumps(data)
return HttpResponse(json_data)
except BaseException as msg:
data = {'remoteRestoreStatus': 0, 'error_message': str(msg)}
json_data = json.dumps(data)
return HttpResponse(json_data)

View File

@@ -1542,3 +1542,67 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
}); });
///** Backup site ends **/// ///** Backup site ends **///
//*** Remote Backup site ****//
app.controller('backupLogsScheduled', function ($scope, $http, $timeout) {
$scope.cyberpanelLoading = true;
$scope.logDetails = true;
$scope.currentPage = 1;
$scope.recordsToShow = 10;
$scope.fetchLogs = function () {
$scope.cyberpanelLoading = false;
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var data = {
logFile: $scope.logFile,
recordsToShow: $scope.recordsToShow,
page: $scope.currentPage
};
dataurl = "/backup/fetchLogs";
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
function ListInitialData(response) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
$scope.logDetails = false;
$scope.logs = JSON.parse(response.data.logs);
$scope.pagination = response.data.pagination;
$scope.jobSuccessSites = response.data.jobSuccessSites;
$scope.jobFailedSites = response.data.jobFailedSites;
$scope.location = response.data.location;
} else {
new PNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberpanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
});
///** Backup site ends **///

View File

@@ -0,0 +1,125 @@
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "Backup Logs - CyberPanel" %}{% endblock %}
{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
<div class="container">
<div id="page-title">
<h2>{% trans "Backup Logs" %}</h2>
<p>{% trans "On this page you can view detailed logs of your local and remote scheduled backups." %}</p>
</div>
<div ng-controller="backupLogsScheduled" class="panel">
<div class="panel-body">
<h3 class="title-hero">
{% trans "Restore Website" %} <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 Log File" %}</label>
<div class="col-sm-6">
<select ng-change="fetchLogs()" ng-model="logFile" class="form-control">
{% for items in backups %}
<option>{{ items }}</option>
{% endfor %}
</select>
</div>
</div>
</form>
<div ng-hide="logDetails" class="form-group">
<div style="margin-bottom: 2%" class="col-sm-12">
<table class="table" style="margin: 0px; padding: 0px">
<thead>
<tr>
<th>{% trans "Successful Sites" %}</th>
<th>{% trans "Failed Sites" %}</th>
<th>{% trans "Location" %}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{$ jobSuccessSites $}</td>
<td>{$ jobFailedSites $}</td>
<td>{$ location $}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div ng-hide="logDetails" class="col-sm-10"
style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888; margin-bottom: 2%">
<input placeholder="Search..."
ng-model="packSearch" name="packSearch" type="text"
class="form-control" required>
</div>
<div ng-hide="logDetails" class="col-sm-2">
<div class="form-group">
<select ng-model="recordsToShow" ng-change="fetchLogs()"
class="form-control" id="example-select">
<option>10</option>
<option>50</option>
<option>100</option>
<option>500</option>
</select>
</div>
</div>
<div ng-hide="logDetails" class="form-group">
<div class="col-sm-12">
<table class="table" style="margin: 0px; padding: 0px">
<thead>
<tr>
<th>{% trans "LEVEL" %}</th>
<th>{% trans "Message" %}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="log in logs | filter:packSearch">
<td ng-bind="log.LEVEL"></td>
<td ng-bind="log.Message"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div ng-hide="logDetails" style="margin-top: 2%" class="row">
<div style="margin-top: 2%" class="col-md-12">
<div class="row">
<div class="col-md-9">
</div>
<div class="col-md-3">
<div class="form-group">
<select ng-model="currentPage" class="form-control"
ng-change="fetchLogs()">
<option ng-repeat="page in pagination">{$ $index + 1 $}
</option>
</select>
</div>
</div>
</div> <!-- end row -->
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -11,7 +11,7 @@
<div class="container"> <div class="container">
<div id="page-title"> <div id="page-title">
<h2>{% trans "Schedule Back up" %} - <a target="_blank" href="http://go.cyberpanel.net/remote-backup" <h2>{% trans "Schedule Back up" %} - <a target="_blank" href="http://go.cyberpanel.net/remote-backup"
style="height: 23px;line-height: 21px;" style="height: 23px;line-height: 21px; text-decoration: underline"
class="btn btn-border btn-alt border-red btn-link font-red" class="btn btn-border btn-alt border-red btn-link font-red"
title=""><span>{% trans "Remote Backups" %}</span></a></h2> title=""><span>{% trans "Remote Backups" %}</span></a></h2>
<p>{% trans "On this page you can schedule Back ups to localhost or remote server (If you have added one)." %}</p> <p>{% trans "On this page you can schedule Back ups to localhost or remote server (If you have added one)." %}</p>
@@ -20,8 +20,11 @@
<div ng-controller="scheduleBackup" class="panel"> <div ng-controller="scheduleBackup" class="panel">
<div class="panel-body"> <div class="panel-body">
<h3 class="title-hero"> <h3 class="title-hero">
{% trans "Schedule Back up" %} <img ng-hide="scheduleBackupLoading" {% trans "Schedule Back up" %} - <img ng-hide="scheduleBackupLoading"
src="{% static 'images/loading.gif' %}"> src="{% static 'images/loading.gif' %}"> <a target="_blank"
href="{% url 'backupLogs' %}"
style="height: 23px;line-height: 21px;"
title="">{% trans "Backup Logs" %}</a>
</h3> </h3>
<div class="example-box-wrapper"> <div class="example-box-wrapper">

View File

@@ -48,7 +48,7 @@ urlpatterns = [
url(r'^localInitiate$', views.localInitiate, name='localInitiate'), url(r'^localInitiate$', views.localInitiate, name='localInitiate'),
url(r'^backupLogs$', views.backupLogs, name='backupLogs'),
url(r'^fetchLogs$', views.fetchLogs, name='fetchLogs'),
] ]

View File

@@ -327,6 +327,23 @@ def cancelRemoteBackup(request):
except KeyError: except KeyError:
return redirect(loadLoginPage) return redirect(loadLoginPage)
def backupLogs(request):
try:
userID = request.session['userID']
bm = BackupManager()
return bm.backupLogs(request, userID)
except KeyError:
return redirect(loadLoginPage)
def fetchLogs(request):
try:
userID = request.session['userID']
wm = BackupManager()
return wm.fetchLogs(userID, json.loads(request.body))
except KeyError:
return redirect(loadLoginPage)
@csrf_exempt @csrf_exempt
def localInitiate(request): def localInitiate(request):

View File

@@ -12,7 +12,7 @@ import os
import time import time
from plogical.backupUtilities import backupUtilities from plogical.backupUtilities import backupUtilities
from re import match,I,M from re import match,I,M
from websiteFunctions.models import Backups from websiteFunctions.models import Backups, BackupJob, BackupJobLogs
from plogical.processUtilities import ProcessUtilities from plogical.processUtilities import ProcessUtilities
from random import randint from random import randint
import json, requests import json, requests
@@ -22,14 +22,22 @@ import signal
class backupSchedule: class backupSchedule:
now = datetime.now() now = datetime.now()
LOCAL = 0
REMOTE = 1
INFO = 0
ERROR = 1
backupLog = ''
@staticmethod @staticmethod
def remoteBackupLogging(fileName, message): def remoteBackupLogging(fileName, message, status = 0):
try: try:
file = open(fileName,'a') file = open(fileName,'a')
file.writelines("[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] "+ message + "\n") file.writelines("[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] "+ message + "\n")
print(("[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] "+ message + "\n")) print(("[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] "+ message + "\n"))
file.close() file.close()
BackupJobLogs(owner=backupSchedule.backupLog, status=status, message="[" + time.strftime("%m.%d.%Y_%H-%M-%S") + "] "+ message).save()
except IOError as msg: except IOError as msg:
return "Can not write to error file." return "Can not write to error file."
@@ -120,18 +128,25 @@ class backupSchedule:
except: except:
pass pass
backupSchedule.remoteBackupLogging(backupLogPath, "An error occurred, Error message: " + status) backupSchedule.remoteBackupLogging(backupLogPath, "Local backup creating failed for %s, Error message: %s" % (virtualHost, status), backupSchedule.ERROR)
try: try:
os.remove(pathToFile) os.remove(pathToFile)
except: except:
pass pass
return 0, tempStoragePath return 0, tempStoragePath
elif os.path.exists(schedulerPath): elif os.path.exists(schedulerPath):
backupSchedule.remoteBackupLogging(backupLogPath, 'Backup process killed without reporting any error.',
backupSchedule.ERROR)
os.remove(schedulerPath) os.remove(schedulerPath)
return 0, 'Backup process killed without reporting any error.' return 0, 'Backup process killed without reporting any error.'
except BaseException as msg: except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [119:startBackup]") logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [119:startBackup]")
backupSchedule.remoteBackupLogging(backupLogPath,
"Local backup creating failed for %s, Error message: %s" % (
virtualHost, str(msg)), backupSchedule.ERROR)
return 0, str(msg) return 0, str(msg)
@staticmethod @staticmethod

View File

@@ -29,6 +29,12 @@ class backupScheduleLocal:
backupRunTime = time.strftime("%m.%d.%Y_%H-%M-%S") backupRunTime = time.strftime("%m.%d.%Y_%H-%M-%S")
backupLogPath = "/usr/local/lscp/logs/local_backup_log." + backupRunTime backupLogPath = "/usr/local/lscp/logs/local_backup_log." + backupRunTime
jobSuccessSites = 0
jobFailedSites = 0
backupSchedule.backupLog = BackupJob(logFile=backupLogPath, location=backupSchedule.LOCAL, jobSuccessSites=jobSuccessSites, jobFailedSites=jobFailedSites)
backupSchedule.backupLog.save()
writeToFile = open(backupLogPath, "a") writeToFile = open(backupLogPath, "a")
backupSchedule.remoteBackupLogging(backupLogPath, "#################################################") backupSchedule.remoteBackupLogging(backupLogPath, "#################################################")
@@ -43,6 +49,9 @@ class backupScheduleLocal:
try: try:
retValues = backupSchedule.createLocalBackup(virtualHost, backupLogPath) retValues = backupSchedule.createLocalBackup(virtualHost, backupLogPath)
if retValues[0] == 0:
continue
if os.path.exists(backupScheduleLocal.localBackupPath): if os.path.exists(backupScheduleLocal.localBackupPath):
backupPath = retValues[1] + ".tar.gz" backupPath = retValues[1] + ".tar.gz"
localBackupPath = '%s/%s' % (open(backupScheduleLocal.localBackupPath, 'r').read().rstrip('/'), backupRunTime) localBackupPath = '%s/%s' % (open(backupScheduleLocal.localBackupPath, 'r').read().rstrip('/'), backupRunTime)
@@ -52,10 +61,14 @@ class backupScheduleLocal:
command = 'mv %s %s' % (backupPath, localBackupPath) command = 'mv %s %s' % (backupPath, localBackupPath)
ProcessUtilities.normalExecutioner(command) ProcessUtilities.normalExecutioner(command)
except BaseException as msg:
backupSchedule.remoteBackupLogging(backupLogPath,
'[ERROR] Backup failed for %s, error: %s moving on..' % (virtualHost, str(msg)))
jobSuccessSites = jobSuccessSites + 1
except BaseException as msg:
jobFailedSites = jobFailedSites + 1
backupSchedule.remoteBackupLogging(backupLogPath,
'[ERROR] Backup failed for %s, error: %s moving on..' % (virtualHost, str(msg)), backupSchedule.ERROR)
@@ -71,6 +84,11 @@ class backupScheduleLocal:
writeToFile.close() writeToFile.close()
job = BackupJob.objects.get(logFile=backupLogPath)
job.jobFailedSites = jobFailedSites
job.jobSuccessSites = jobSuccessSites
job.save()
except BaseException as msg: except BaseException as msg:
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [214:startBackup]") logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [214:startBackup]")

View File

@@ -93,7 +93,6 @@ def litespeedStatus(request):
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[litespeedStatus]") logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[litespeedStatus]")
return redirect(loadLoginPage) return redirect(loadLoginPage)
def stopOrRestartLitespeed(request): def stopOrRestartLitespeed(request):
try: try:
userID = request.session['userID'] userID = request.session['userID']
@@ -127,7 +126,6 @@ def stopOrRestartLitespeed(request):
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[stopOrRestartLitespeed]") logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[stopOrRestartLitespeed]")
return HttpResponse("Not Logged in as admin") return HttpResponse("Not Logged in as admin")
def cyberCPMainLogFile(request): def cyberCPMainLogFile(request):
try: try:
userID = request.session['userID'] userID = request.session['userID']
@@ -145,7 +143,6 @@ def cyberCPMainLogFile(request):
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[cyberCPMainLogFile]") logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[cyberCPMainLogFile]")
return redirect(loadLoginPage) return redirect(loadLoginPage)
def getFurtherDataFromLogFile(request): def getFurtherDataFromLogFile(request):
try: try:
userID = request.session['userID'] userID = request.session['userID']
@@ -196,7 +193,6 @@ def services(request):
except KeyError: except KeyError:
return redirect(loadLoginPage) return redirect(loadLoginPage)
def servicesStatus(request): def servicesStatus(request):
try: try:
userID = request.session['userID'] userID = request.session['userID']
@@ -291,7 +287,6 @@ def servicesStatus(request):
except KeyError: except KeyError:
return redirect(loadLoginPage) return redirect(loadLoginPage)
def servicesAction(request): def servicesAction(request):
try: try:
userID = request.session['userID'] userID = request.session['userID']
@@ -344,7 +339,6 @@ def servicesAction(request):
final_json = json.dumps(final_dic) final_json = json.dumps(final_dic)
return HttpResponse(final_json) return HttpResponse(final_json)
def switchTOLSWS(request): def switchTOLSWS(request):
try: try:
userID = request.session['userID'] userID = request.session['userID']
@@ -378,7 +372,6 @@ def switchTOLSWS(request):
json_data = json.dumps(data_ret) json_data = json.dumps(data_ret)
return HttpResponse(json_data) return HttpResponse(json_data)
def switchTOLSWSStatus(request): def switchTOLSWSStatus(request):
try: try:

View File

@@ -1542,3 +1542,67 @@ app.controller('remoteBackupControl', function ($scope, $http, $timeout) {
}); });
///** Backup site ends **/// ///** Backup site ends **///
//*** Remote Backup site ****//
app.controller('backupLogsScheduled', function ($scope, $http, $timeout) {
$scope.cyberpanelLoading = true;
$scope.logDetails = true;
$scope.currentPage = 1;
$scope.recordsToShow = 10;
$scope.fetchLogs = function () {
$scope.cyberpanelLoading = false;
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
var data = {
logFile: $scope.logFile,
recordsToShow: $scope.recordsToShow,
page: $scope.currentPage
};
dataurl = "/backup/fetchLogs";
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
function ListInitialData(response) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
$scope.logDetails = false;
$scope.logs = JSON.parse(response.data.logs);
$scope.pagination = response.data.pagination;
$scope.jobSuccessSites = response.data.jobSuccessSites;
$scope.jobFailedSites = response.data.jobFailedSites;
$scope.location = response.data.location;
} else {
new PNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberpanelLoading = true;
new PNotify({
title: 'Operation Failed!',
text: 'Could not connect to server, please refresh this page',
type: 'error'
});
}
};
});
///** Backup site ends **///