2025-08-01 14:56:30 +05:00
|
|
|
import json
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import paramiko
|
|
|
|
|
sys.path.append('/usr/local/CyberCP')
|
|
|
|
|
import django
|
|
|
|
|
|
|
|
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
|
|
|
|
try:
|
|
|
|
|
django.setup()
|
|
|
|
|
from ApachController.ApacheVhosts import ApacheVhost
|
|
|
|
|
from plogical.acl import ACLManager
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from plogical.randomPassword import generate_pass
|
|
|
|
|
import pexpect
|
|
|
|
|
from plogical import CyberCPLogFileWriter as logging
|
|
|
|
|
import subprocess
|
|
|
|
|
import shlex
|
|
|
|
|
from shutil import make_archive, rmtree
|
|
|
|
|
from plogical import mysqlUtilities
|
|
|
|
|
import tarfile
|
|
|
|
|
from multiprocessing import Process
|
|
|
|
|
import signal
|
|
|
|
|
from plogical.installUtilities import installUtilities
|
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from plogical.virtualHostUtilities import virtualHostUtilities
|
|
|
|
|
from plogical.sslUtilities import sslUtilities
|
|
|
|
|
from plogical.mailUtilities import mailUtilities
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
from xml.etree.ElementTree import Element, SubElement
|
|
|
|
|
from xml.etree import ElementTree
|
|
|
|
|
from xml.dom import minidom
|
|
|
|
|
import time
|
|
|
|
|
from shutil import copy
|
|
|
|
|
from random import randint
|
|
|
|
|
from plogical.processUtilities import ProcessUtilities
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from websiteFunctions.models import Websites, ChildDomains, Backups, NormalBackupDests
|
|
|
|
|
from databases.models import Databases
|
|
|
|
|
from loginSystem.models import Administrator
|
|
|
|
|
from plogical.dnsUtilities import DNS
|
|
|
|
|
from mailServer.models import Domains as eDomains
|
|
|
|
|
from backup.models import DBUsers
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
VERSION = '2.4'
|
2025-09-01 13:11:42 +05:00
|
|
|
BUILD = 4
|
2025-08-01 14:56:30 +05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
## I am not the monster that you think I am..
|
|
|
|
|
|
|
|
|
|
class backupUtilities:
|
|
|
|
|
Server_root = "/usr/local/lsws"
|
|
|
|
|
completeKeyPath = "/home/cyberpanel/.ssh"
|
|
|
|
|
destinationsPath = "/home/cyberpanel/destinations"
|
|
|
|
|
licenseKey = '/usr/local/lsws/conf/license.key'
|
|
|
|
|
NiceDefault = '10'
|
|
|
|
|
CPUDefault = '1000'
|
|
|
|
|
CloudBackupConfigPath = '/home/cyberpanel/CloudBackup.json'
|
|
|
|
|
time = 10
|
|
|
|
|
|
|
|
|
|
def __init__(self, extraArgs):
|
|
|
|
|
self.extraArgs = extraArgs
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def prepareBackupMeta(backupDomain, backupName, tempStoragePath, backupPath, FromInner=1):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
website = Websites.objects.get(domain=backupDomain)
|
|
|
|
|
|
|
|
|
|
connection, cursor = mysqlUtilities.mysqlUtilities.setupConnection()
|
|
|
|
|
|
|
|
|
|
if FromInner:
|
|
|
|
|
status = os.path.join(backupPath, 'status')
|
|
|
|
|
#logging.CyberCPLogFileWriter.statusWriter(status, 'Setting up meta data..')
|
|
|
|
|
command = f"echo 'Setting up meta data..' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
else:
|
|
|
|
|
status = '/home/cyberpanel/dummy'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Creating meta for {backupDomain}.')
|
|
|
|
|
|
|
|
|
|
######### Generating meta
|
|
|
|
|
|
|
|
|
|
## XML Generation
|
|
|
|
|
|
|
|
|
|
metaFileXML = Element('metaFile')
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'VERSION')
|
|
|
|
|
child.text = VERSION
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'BUILD')
|
|
|
|
|
child.text = str(BUILD)
|
|
|
|
|
|
|
|
|
|
### try to take care of - https://github.com/usmannasir/cyberpanel/issues/1196
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'BackupWholeDir')
|
|
|
|
|
child.text = str(1)
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'masterDomain')
|
|
|
|
|
child.text = backupDomain
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'phpSelection')
|
|
|
|
|
child.text = website.phpSelection
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'externalApp')
|
|
|
|
|
child.text = website.externalApp
|
|
|
|
|
|
|
|
|
|
### Find user of site
|
|
|
|
|
|
|
|
|
|
siteUser = website.admin
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'userName')
|
|
|
|
|
child.text = siteUser.userName
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'userPassword')
|
|
|
|
|
child.text = siteUser.password
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'firstName')
|
|
|
|
|
child.text = siteUser.firstName
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'lastName')
|
|
|
|
|
child.text = siteUser.lastName
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'email')
|
|
|
|
|
child.text = siteUser.email
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'type')
|
|
|
|
|
child.text = str(siteUser.type)
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'owner')
|
|
|
|
|
child.text = str(siteUser.owner)
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'token')
|
|
|
|
|
child.text = siteUser.token
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'api')
|
|
|
|
|
child.text = str(siteUser.api)
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'securityLevel')
|
|
|
|
|
child.text = str(siteUser.securityLevel)
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'state')
|
|
|
|
|
child.text = siteUser.state
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'initWebsitesLimit')
|
|
|
|
|
child.text = str(siteUser.initWebsitesLimit)
|
|
|
|
|
|
|
|
|
|
child = SubElement(metaFileXML, 'aclName')
|
|
|
|
|
child.text = siteUser.acl.name
|
|
|
|
|
|
|
|
|
|
#####################
|
|
|
|
|
|
|
|
|
|
childDomains = website.childdomains_set.all()
|
|
|
|
|
|
|
|
|
|
databases = website.databases_set.all()
|
|
|
|
|
|
|
|
|
|
## Child domains XML
|
|
|
|
|
|
|
|
|
|
childDomainsXML = Element('ChildDomains')
|
|
|
|
|
|
|
|
|
|
for items in childDomains:
|
|
|
|
|
childDomainXML = Element('domain')
|
|
|
|
|
|
|
|
|
|
child = SubElement(childDomainXML, 'domain')
|
|
|
|
|
child.text = items.domain
|
|
|
|
|
child = SubElement(childDomainXML, 'phpSelection')
|
|
|
|
|
child.text = items.phpSelection
|
|
|
|
|
child = SubElement(childDomainXML, 'path')
|
|
|
|
|
child.text = items.path
|
|
|
|
|
|
|
|
|
|
childDomainsXML.append(childDomainXML)
|
|
|
|
|
|
|
|
|
|
metaFileXML.append(childDomainsXML)
|
|
|
|
|
|
|
|
|
|
## Databases XML
|
|
|
|
|
|
|
|
|
|
databasesXML = Element('Databases')
|
|
|
|
|
|
|
|
|
|
for items in databases:
|
|
|
|
|
|
|
|
|
|
databaseXML = Element('database')
|
|
|
|
|
|
|
|
|
|
child = SubElement(databaseXML, 'dbName')
|
|
|
|
|
child.text = str(items.dbName)
|
|
|
|
|
|
|
|
|
|
cursor.execute(f"select user,host from mysql.db where db='{items.dbName}'")
|
|
|
|
|
databaseUsers = cursor.fetchall()
|
|
|
|
|
|
|
|
|
|
for databaseUser in databaseUsers:
|
|
|
|
|
|
|
|
|
|
databaseUserXML = Element('databaseUsers')
|
|
|
|
|
|
|
|
|
|
child = SubElement(databaseUserXML, 'dbUser')
|
|
|
|
|
child.text = databaseUser[0]
|
|
|
|
|
|
|
|
|
|
child = SubElement(databaseUserXML, 'dbHost')
|
|
|
|
|
child.text = databaseUser[1]
|
|
|
|
|
|
|
|
|
|
## Fetch user password
|
|
|
|
|
dbuser = DBUsers.objects.get(user=databaseUser[0], host=databaseUser[1])
|
|
|
|
|
child = SubElement(databaseUserXML, 'password')
|
|
|
|
|
child.text = str(dbuser.password)
|
|
|
|
|
|
|
|
|
|
databaseXML.append(databaseUserXML)
|
|
|
|
|
|
|
|
|
|
databasesXML.append(databaseXML)
|
|
|
|
|
|
|
|
|
|
metaFileXML.append(databasesXML)
|
|
|
|
|
|
|
|
|
|
## Get Aliases
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
aliasesXML = Element('Aliases')
|
|
|
|
|
|
|
|
|
|
aliases = backupUtilities.getAliases(backupDomain)
|
|
|
|
|
|
|
|
|
|
for items in aliases:
|
|
|
|
|
child = SubElement(aliasesXML, 'alias')
|
|
|
|
|
child.text = items
|
|
|
|
|
|
|
|
|
|
metaFileXML.append(aliasesXML)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s. [167:prepMeta]' % (str(msg)))
|
|
|
|
|
|
|
|
|
|
## Finish Alias
|
|
|
|
|
|
|
|
|
|
## DNS Records XML
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
dnsRecordsXML = Element("dnsrecords")
|
|
|
|
|
dnsRecords = DNS.getDNSRecords(backupDomain)
|
|
|
|
|
|
|
|
|
|
for items in dnsRecords:
|
|
|
|
|
dnsRecordXML = Element('dnsrecord')
|
|
|
|
|
|
|
|
|
|
child = SubElement(dnsRecordXML, 'type')
|
|
|
|
|
child.text = items.type
|
|
|
|
|
child = SubElement(dnsRecordXML, 'name')
|
|
|
|
|
child.text = items.name
|
|
|
|
|
child = SubElement(dnsRecordXML, 'content')
|
|
|
|
|
child.text = items.content
|
|
|
|
|
child = SubElement(dnsRecordXML, 'priority')
|
|
|
|
|
child.text = str(items.prio)
|
|
|
|
|
|
|
|
|
|
dnsRecordsXML.append(dnsRecordXML)
|
|
|
|
|
|
|
|
|
|
metaFileXML.append(dnsRecordsXML)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s. [158:prepMeta]' % (str(msg)))
|
|
|
|
|
|
|
|
|
|
## Email accounts XML
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
emailRecordsXML = Element('emails')
|
|
|
|
|
eDomain = eDomains.objects.get(domain=backupDomain)
|
|
|
|
|
emailAccounts = eDomain.eusers_set.all()
|
|
|
|
|
|
|
|
|
|
for items in emailAccounts:
|
|
|
|
|
emailRecordXML = Element('emailAccount')
|
|
|
|
|
|
|
|
|
|
child = SubElement(emailRecordXML, 'email')
|
|
|
|
|
child.text = items.email
|
|
|
|
|
child = SubElement(emailRecordXML, 'password')
|
|
|
|
|
child.text = items.password
|
|
|
|
|
|
|
|
|
|
emailRecordsXML.append(emailRecordXML)
|
|
|
|
|
|
|
|
|
|
metaFileXML.append(emailRecordsXML)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s. [179:prepMeta]' % (str(msg)))
|
|
|
|
|
|
|
|
|
|
## Email meta generated!
|
|
|
|
|
|
|
|
|
|
def prettify(elem):
|
|
|
|
|
"""Return a pretty-printed XML string for the Element.
|
|
|
|
|
"""
|
|
|
|
|
rough_string = ElementTree.tostring(elem, 'utf-8')
|
|
|
|
|
reparsed = minidom.parseString(rough_string)
|
|
|
|
|
return reparsed.toprettyxml(indent=" ")
|
|
|
|
|
|
|
|
|
|
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52/meta.xml -- metaPath
|
|
|
|
|
|
|
|
|
|
metaPath = '/tmp/%s' % (str(randint(1000, 9999)))
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Path to meta file {metaPath}')
|
|
|
|
|
|
|
|
|
|
xmlpretty = prettify(metaFileXML).encode('ascii', 'ignore')
|
|
|
|
|
metaFile = open(metaPath, 'w')
|
|
|
|
|
metaFile.write(xmlpretty.decode())
|
|
|
|
|
metaFile.close()
|
|
|
|
|
os.chmod(metaPath, 0o600)
|
|
|
|
|
|
|
|
|
|
## meta generated
|
|
|
|
|
|
|
|
|
|
if FromInner:
|
|
|
|
|
newBackup = Backups(website=website, fileName=backupName, date=time.strftime("%m.%d.%Y_%H-%M-%S"),
|
|
|
|
|
size=0, status=1)
|
|
|
|
|
newBackup.save()
|
|
|
|
|
|
|
|
|
|
command = f"echo 'Meta data is ready..' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
|
|
|
|
|
return 1, 'None', metaPath
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f"{str(msg)} [207][5009]")
|
|
|
|
|
if FromInner:
|
|
|
|
|
#logging.CyberCPLogFileWriter.statusWriter(status, "%s [207][5009]" % (str(msg)), status)
|
|
|
|
|
command = f"echo '{status} [207][5009]' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
return 0, str(msg), 'None'
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def startBackup(tempStoragePath, backupName, backupPath, metaPath=None):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52 -- tempStoragePath
|
|
|
|
|
## /home/example.com/backup - backupPath
|
|
|
|
|
|
|
|
|
|
##### Writing the name of backup file.
|
|
|
|
|
|
|
|
|
|
## /home/example.com/backup/backupFileName
|
|
|
|
|
pidFile = f'{backupPath}startBackup'
|
|
|
|
|
writeToFile = open(pidFile, 'w')
|
|
|
|
|
writeToFile.writelines(str(os.getpid()))
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
backupFileNamePath = os.path.join(backupPath, "backupFileName")
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(backupFileNamePath, backupName)
|
|
|
|
|
|
|
|
|
|
#####
|
|
|
|
|
|
|
|
|
|
status = os.path.join(backupPath, 'status')
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Making archive of home directory.\n")
|
|
|
|
|
|
|
|
|
|
##### Parsing XML Meta file!
|
|
|
|
|
|
|
|
|
|
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52 -- tempStoragePath
|
|
|
|
|
|
|
|
|
|
metaPathInBackup = os.path.join(tempStoragePath, 'meta.xml')
|
|
|
|
|
|
|
|
|
|
if metaPath != None:
|
|
|
|
|
writeToFile = open(metaPathInBackup, 'w')
|
|
|
|
|
writeToFile.write(open(metaPath, 'r').read())
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
backupMetaData = ElementTree.parse(metaPathInBackup)
|
|
|
|
|
|
|
|
|
|
##### Making archive of home directory
|
|
|
|
|
|
|
|
|
|
domainName = backupMetaData.find('masterDomain').text
|
|
|
|
|
|
|
|
|
|
## Saving original vhost conf file
|
|
|
|
|
|
|
|
|
|
#completPathToConf = f'{backupUtilities.Server_root}/conf/vhosts/{domainName}/vhost.conf'
|
|
|
|
|
|
|
|
|
|
#copy(completPathToConf, tempStoragePath + '/vhost.conf')
|
|
|
|
|
|
|
|
|
|
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52 -- tempStoragePath
|
|
|
|
|
## shutil.make_archive
|
|
|
|
|
|
|
|
|
|
## Stop making archive of document_root and copy instead
|
|
|
|
|
|
|
|
|
|
from shutil import copytree
|
|
|
|
|
|
|
|
|
|
#copytree('/home/%s/public_html' % domainName, '%s/%s' % (tempStoragePath, 'public_html'))
|
|
|
|
|
#command = f'cp -R /home/{domainName}/public_html {tempStoragePath}/public_html'
|
|
|
|
|
### doing backup of whole dir and keeping it in public_html folder will restore from here - ref https://github.com/usmannasir/cyberpanel/issues/1196
|
|
|
|
|
command = f"rsync -av --ignore-errors --exclude=.wp-cli --exclude=logs --exclude=backup --exclude=lscache /home/{domainName}/ {tempStoragePath}/public_html/"
|
|
|
|
|
ProcessUtilities.normalExecutioner(command)
|
|
|
|
|
# if ProcessUtilities.normalExecutioner(command) == 0:
|
|
|
|
|
# raise BaseException(f'Failed to run cp command during backup generation.')
|
|
|
|
|
|
|
|
|
|
# make_archive(os.path.join(tempStoragePath,"public_html"), 'gztar', os.path.join("/home",domainName,"public_html"))
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Backing up databases..")
|
|
|
|
|
print('1,None')
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
# try:
|
|
|
|
|
# os.remove(os.path.join(backupPath, backupName + ".tar.gz"))
|
|
|
|
|
# except:
|
|
|
|
|
# pass
|
|
|
|
|
#
|
|
|
|
|
# try:
|
|
|
|
|
# rmtree(tempStoragePath)
|
|
|
|
|
# except:
|
|
|
|
|
# pass
|
|
|
|
|
|
|
|
|
|
status = os.path.join(backupPath, 'status')
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Aborted, " + str(msg) + ".[365] [5009]")
|
|
|
|
|
print(f"Aborted, {str(msg)}.[365] [5009]")
|
|
|
|
|
try:
|
|
|
|
|
os.remove(pidFile)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def BackupRoot(tempStoragePath, backupName, backupPath, metaPath=None, externalApp = None, CPHomeStorage=None):
|
|
|
|
|
|
|
|
|
|
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52 -- tempStoragePath
|
|
|
|
|
## /home/example.com/backup - backupPath
|
|
|
|
|
## /home/backup/<random_number> - CPHomeStorage
|
|
|
|
|
|
|
|
|
|
### CPHomeStorage /home/cyberpanel/<random_number>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pidFile = '%sBackupRoot' % (backupPath)
|
|
|
|
|
|
|
|
|
|
writeToFile = open(pidFile, 'w')
|
|
|
|
|
writeToFile.writelines(str(os.getpid()))
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
status = os.path.join(backupPath, 'status')
|
|
|
|
|
metaPathInBackup = os.path.join(tempStoragePath, 'meta.xml')
|
|
|
|
|
backupMetaData = ElementTree.parse(metaPathInBackup)
|
|
|
|
|
|
|
|
|
|
domainName = backupMetaData.find('masterDomain').text
|
|
|
|
|
##### Saving SSL Certificates if any
|
|
|
|
|
|
|
|
|
|
sslStoragePath = '/etc/letsencrypt/live/' + domainName
|
|
|
|
|
|
|
|
|
|
if os.path.exists(sslStoragePath):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
copy(os.path.join(sslStoragePath, "cert.pem"), os.path.join(CPHomeStorage, domainName + ".cert.pem"))
|
|
|
|
|
|
|
|
|
|
copy(os.path.join(sslStoragePath, "fullchain.pem"),os.path.join(CPHomeStorage, domainName + ".fullchain.pem"))
|
|
|
|
|
|
|
|
|
|
copy(os.path.join(sslStoragePath, "privkey.pem"),os.path.join(CPHomeStorage, domainName + ".privkey.pem"))
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'{str(msg)}. [283:startBackup]')
|
|
|
|
|
|
|
|
|
|
## Child Domains SSL.
|
|
|
|
|
|
|
|
|
|
## For master domain copy the conf file to tempStorage path here it was done above, but since it is root operation it should be performed here
|
|
|
|
|
|
|
|
|
|
completPathToConf = f'{backupUtilities.Server_root}/conf/vhosts/{domainName}/vhost.conf'
|
|
|
|
|
|
|
|
|
|
### If domain is suspended, this path wont exists, so please check for other
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if os.path.exists(completPathToConf):
|
|
|
|
|
copy(completPathToConf, f'{CPHomeStorage}/vhost.conf')
|
|
|
|
|
else:
|
|
|
|
|
completPathToConf = f'{backupUtilities.Server_root}/conf/vhosts/{domainName}-suspended/vhost.conf'
|
|
|
|
|
if os.path.exists(completPathToConf):
|
|
|
|
|
#copy(completPathToConf, tempStoragePath + '/vhost.conf')
|
|
|
|
|
|
|
|
|
|
copy(completPathToConf, f'{CPHomeStorage}/vhost.conf')
|
|
|
|
|
|
|
|
|
|
#### also backup apache conf if available
|
|
|
|
|
from ApachController.ApacheVhosts import ApacheVhost
|
|
|
|
|
|
|
|
|
|
finalConfPathApache = ApacheVhost.configBasePath + domainName + '.conf'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(finalConfPathApache):
|
|
|
|
|
copy(finalConfPathApache, f'{CPHomeStorage}/apache.conf')
|
|
|
|
|
|
|
|
|
|
childDomains = backupMetaData.findall('ChildDomains/domain')
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
for childDomain in childDomains:
|
|
|
|
|
|
|
|
|
|
actualChildDomain = childDomain.find('domain').text
|
|
|
|
|
childPath = childDomain.find('path').text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
completPathToConf = f'{backupUtilities.Server_root}/conf/vhosts/{actualChildDomain}/vhost.conf'
|
|
|
|
|
TempConfPath = f'/home/cyberpanel/{actualChildDomain}.vhost.conf'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(completPathToConf):
|
|
|
|
|
#copy(completPathToConf, f'{tempStoragePath}/{actualChildDomain}.vhost.conf')
|
|
|
|
|
copy(completPathToConf, f'{CPHomeStorage}/{actualChildDomain}.vhost.conf')
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
completPathToConf = f'{backupUtilities.Server_root}/conf/vhosts/{actualChildDomain}-suspended/vhost.conf'
|
|
|
|
|
if os.path.exists(completPathToConf):
|
|
|
|
|
#copy(completPathToConf, f'{tempStoragePath}/{actualChildDomain}.vhost.conf')
|
|
|
|
|
copy(completPathToConf, f'{CPHomeStorage}/{actualChildDomain}.vhost.conf')
|
|
|
|
|
|
|
|
|
|
### also backup apache conf if available
|
|
|
|
|
|
|
|
|
|
finalConfPathApacheChild = ApacheVhost.configBasePath + actualChildDomain + '.conf'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(finalConfPathApacheChild):
|
|
|
|
|
copy(finalConfPathApacheChild, f'{CPHomeStorage}/{actualChildDomain}.apache.conf')
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
### Storing SSL for child domainsa
|
|
|
|
|
|
|
|
|
|
sslStoragePath = f'/etc/letsencrypt/live/{actualChildDomain}'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(sslStoragePath):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
#copy(os.path.join(sslStoragePath, "cert.pem"), os.path.join(tempStoragePath, actualChildDomain + ".cert.pem"))
|
|
|
|
|
copy(os.path.join(sslStoragePath, "cert.pem"),os.path.join(CPHomeStorage, actualChildDomain + ".cert.pem"))
|
|
|
|
|
|
|
|
|
|
#copy(os.path.join(sslStoragePath, "fullchain.pem"),os.path.join(tempStoragePath, actualChildDomain + ".fullchain.pem"))
|
|
|
|
|
copy(os.path.join(sslStoragePath, "fullchain.pem"),os.path.join(CPHomeStorage, actualChildDomain + ".fullchain.pem"))
|
|
|
|
|
|
|
|
|
|
#copy(os.path.join(sslStoragePath, "privkey.pem"),os.path.join(tempStoragePath, actualChildDomain + ".privkey.pem"))
|
|
|
|
|
copy(os.path.join(sslStoragePath, "privkey.pem"),os.path.join(CPHomeStorage, actualChildDomain + ".privkey.pem"))
|
|
|
|
|
|
|
|
|
|
#make_archive(os.path.join(tempStoragePath, "sslData-" + domainName), 'gztar', sslStoragePath)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
## no need to do this as on line 380 whole dir will be backuped up
|
|
|
|
|
|
|
|
|
|
# if childPath.find(f'/home/{domainName}/public_html') == -1:
|
|
|
|
|
# # copy_tree(childPath, '%s/%s-docroot' % (tempStoragePath, actualChildDomain))
|
|
|
|
|
# command = f'cp -R {childPath} {tempStoragePath}/{actualChildDomain}-docroot'
|
|
|
|
|
# ProcessUtilities.executioner(command, externalApp)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
## backup emails
|
|
|
|
|
|
|
|
|
|
domainName = backupMetaData.find('masterDomain').text
|
|
|
|
|
|
|
|
|
|
if os.path.islink(status) or os.path.islink(tempStoragePath or os.path.islink(backupPath)) or os.path.islink(
|
|
|
|
|
metaPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('symlinked.')
|
|
|
|
|
#logging.CyberCPLogFileWriter.statusWriter(status, 'Symlink attack. [365][5009]')
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
## backup email accounts
|
|
|
|
|
|
|
|
|
|
if externalApp == None:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Backing up email accounts..\n")
|
|
|
|
|
else:
|
|
|
|
|
command = f"echo 'Backing up email accounts..' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
emailPath = f'/home/vmail/{domainName}'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(emailPath):
|
|
|
|
|
# copy_tree(emailPath, '%s/vmail' % (tempStoragePath), preserve_symlinks=True)
|
|
|
|
|
command = f'cp -R {emailPath} {CPHomeStorage}/vmail'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
## shutil.make_archive. Creating final package.
|
|
|
|
|
|
|
|
|
|
if externalApp == None:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Preparing final compressed package..\n")
|
|
|
|
|
else:
|
|
|
|
|
command = f"echo 'Preparing final compressed package..' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp, True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### change own of CPHomeStorage and move data
|
|
|
|
|
|
|
|
|
|
command = f'chown -R {externalApp}:{externalApp} {CPHomeStorage}'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = f'mv {CPHomeStorage}/* {tempStoragePath}/'
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp, True)
|
|
|
|
|
|
|
|
|
|
#make_archive(os.path.join(backupPath, backupName), 'gztar', tempStoragePath)
|
|
|
|
|
#rmtree(tempStoragePath)
|
|
|
|
|
|
|
|
|
|
command = f'tar -czf {backupPath}/{backupName}.tar.gz -C {tempStoragePath} .'
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp, True)
|
|
|
|
|
|
|
|
|
|
### remove leftover storages
|
|
|
|
|
|
|
|
|
|
command = f'rm -rf {tempStoragePath}'
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp)
|
|
|
|
|
|
|
|
|
|
command = f'rm -rf {CPHomeStorage}'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
|
|
backupObs = Backups.objects.filter(fileName=backupName)
|
|
|
|
|
|
|
|
|
|
filePath = f'{backupPath}/{backupName}.tar.gz'
|
|
|
|
|
totalSize = '%sMB' % (str(int(os.path.getsize(filePath) / 1048576)))
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
for items in backupObs:
|
|
|
|
|
items.status = 1
|
|
|
|
|
items.size = totalSize
|
|
|
|
|
items.save()
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s. [backupRoot:499]' % str(msg))
|
|
|
|
|
for items in backupObs:
|
|
|
|
|
items.status = 1
|
|
|
|
|
items.size = totalSize
|
|
|
|
|
items.save()
|
|
|
|
|
|
|
|
|
|
command = 'chmod 600 %s' % (os.path.join(backupPath, backupName + ".tar.gz"))
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
if externalApp == None:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Completed\n")
|
|
|
|
|
else:
|
|
|
|
|
command = f"echo 'Completed' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp, True)
|
|
|
|
|
|
|
|
|
|
os.remove(pidFile)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, '%s. [511:BackupRoot][[5009]]\n' % str(msg))
|
|
|
|
|
if externalApp == None:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, '%s. [511:BackupRoot][[5009]]\n')
|
|
|
|
|
else:
|
|
|
|
|
command = f"echo '%s. [511:BackupRoot][[5009]]' > {status}"
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp)
|
|
|
|
|
|
|
|
|
|
command = f'rm -rf {tempStoragePath}'
|
|
|
|
|
ProcessUtilities.executioner(command, externalApp)
|
|
|
|
|
|
|
|
|
|
command = f'rm -rf {CPHomeStorage}'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def initiateBackup(tempStoragePath, backupName, backupPath):
|
|
|
|
|
try:
|
|
|
|
|
p = Process(target=backupUtilities.startBackup, args=(tempStoragePath, backupName, backupPath,))
|
|
|
|
|
p.start()
|
|
|
|
|
pid = open(backupPath + 'pid', "w")
|
|
|
|
|
pid.write(str(p.pid))
|
|
|
|
|
pid.close()
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [initiateBackup]")
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def createWebsiteFromBackup(backupFileOrig, dir):
|
|
|
|
|
try:
|
|
|
|
|
backupFile = backupFileOrig.strip(".tar.gz")
|
|
|
|
|
originalFile = f"/home/backup/{backupFileOrig}"
|
|
|
|
|
|
|
|
|
|
if os.path.exists(backupFileOrig):
|
|
|
|
|
path = backupFile
|
|
|
|
|
elif not os.path.exists(originalFile):
|
|
|
|
|
dir = dir
|
|
|
|
|
path = "/home/backup/transfer-" + str(dir) + "/" + backupFile
|
|
|
|
|
else:
|
|
|
|
|
path = f"/home/backup/{backupFile}"
|
|
|
|
|
|
|
|
|
|
admin = Administrator.objects.get(userName='admin')
|
|
|
|
|
|
|
|
|
|
## open meta file to read data
|
|
|
|
|
|
|
|
|
|
## Parsing XML Meta file!
|
|
|
|
|
|
|
|
|
|
backupMetaData = ElementTree.parse(os.path.join(path, 'meta.xml'))
|
|
|
|
|
|
|
|
|
|
domain = backupMetaData.find('masterDomain').text
|
|
|
|
|
phpSelection = backupMetaData.find('phpSelection').text
|
|
|
|
|
externalApp = backupMetaData.find('externalApp').text
|
|
|
|
|
VERSION = backupMetaData.find('VERSION').text
|
|
|
|
|
BUILD = backupMetaData.find('BUILD').text
|
|
|
|
|
|
|
|
|
|
### Fetch user details
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
userName = backupMetaData.find('userName').text
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
siteUser = Administrator.objects.get(userName=userName)
|
|
|
|
|
except:
|
|
|
|
|
userPassword = backupMetaData.find('userPassword').text
|
|
|
|
|
firstName = backupMetaData.find('firstName').text
|
|
|
|
|
lastName = backupMetaData.find('lastName').text
|
|
|
|
|
email = backupMetaData.find('email').text
|
|
|
|
|
type = int(backupMetaData.find('type').text)
|
|
|
|
|
owner = int(backupMetaData.find('owner').text)
|
|
|
|
|
token = backupMetaData.find('token').text
|
|
|
|
|
api = int(backupMetaData.find('api').text)
|
|
|
|
|
securityLevel = int(backupMetaData.find('securityLevel').text)
|
|
|
|
|
state = backupMetaData.find('state').text
|
|
|
|
|
initWebsitesLimit = int(backupMetaData.find('initWebsitesLimit').text)
|
|
|
|
|
from loginSystem.models import ACL
|
|
|
|
|
acl = ACL.objects.get(name=backupMetaData.find('aclName').text)
|
|
|
|
|
siteUser = Administrator(userName=userName, password=userPassword, firstName=firstName,
|
|
|
|
|
initWebsitesLimit=initWebsitesLimit, acl=acl,
|
|
|
|
|
lastName=lastName, email=email, type=type, owner=owner, token=token,
|
|
|
|
|
api=api, securityLevel=securityLevel, state=state)
|
|
|
|
|
siteUser.save()
|
|
|
|
|
except:
|
|
|
|
|
siteUser = Administrator.objects.get(userName='admin')
|
|
|
|
|
|
|
|
|
|
## Pre-creation checks
|
|
|
|
|
|
|
|
|
|
if Websites.objects.filter(domain=domain).count() > 0:
|
|
|
|
|
raise BaseException('This website already exists.')
|
|
|
|
|
|
|
|
|
|
if ChildDomains.objects.filter(domain=domain).count() > 0:
|
|
|
|
|
raise BaseException("This website already exists as child domain.")
|
|
|
|
|
|
|
|
|
|
####### Pre-creation checks ends
|
|
|
|
|
|
|
|
|
|
## Create Configurations
|
|
|
|
|
|
|
|
|
|
# result = virtualHostUtilities.createVirtualHost(domain, siteUser.email, phpSelection, externalApp, 0, 1, 0,
|
|
|
|
|
# siteUser.userName, 'Default', 0)
|
|
|
|
|
result = virtualHostUtilities.createVirtualHost(domain, siteUser.email, phpSelection, externalApp, 1, 1, 0,
|
|
|
|
|
siteUser.userName, 'Default', 0, None,
|
|
|
|
|
1)
|
|
|
|
|
|
|
|
|
|
if result[0] == 0:
|
|
|
|
|
raise BaseException(result[1])
|
|
|
|
|
|
|
|
|
|
## Create Configurations ends here
|
|
|
|
|
|
|
|
|
|
## Create databases
|
|
|
|
|
|
|
|
|
|
### This code is just to create databases, database users will be created later
|
|
|
|
|
|
|
|
|
|
databases = backupMetaData.findall('Databases/database')
|
|
|
|
|
website = Websites.objects.get(domain=domain)
|
|
|
|
|
|
|
|
|
|
for database in databases:
|
|
|
|
|
|
|
|
|
|
dbName = database.find('dbName').text
|
|
|
|
|
|
|
|
|
|
if ((VERSION == '2.1' or VERSION == '2.3') and int(BUILD) >= 1) or (VERSION == '2.4' and int(BUILD) >= 0):
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Backup version 2.1.1+ detected..')
|
|
|
|
|
databaseUsers = database.findall('databaseUsers')
|
|
|
|
|
for databaseUser in databaseUsers:
|
|
|
|
|
|
|
|
|
|
dbUser = databaseUser.find('dbUser').text
|
|
|
|
|
res = mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, 'cyberpanel')
|
|
|
|
|
if res == 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'Failed to restore database %s. But it can be false positive, moving on..' % (dbName))
|
|
|
|
|
|
|
|
|
|
newDB = Databases(website=website, dbName=dbName, dbUser=dbUser)
|
|
|
|
|
newDB.save()
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
dbUser = database.find('dbUser').text
|
|
|
|
|
|
|
|
|
|
if mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, "cyberpanel") == 0:
|
|
|
|
|
raise BaseException
|
|
|
|
|
|
|
|
|
|
newDB = Databases(website=website, dbName=dbName, dbUser=dbUser)
|
|
|
|
|
newDB.save()
|
|
|
|
|
|
|
|
|
|
## Create dns zone
|
|
|
|
|
|
|
|
|
|
dnsrecords = backupMetaData.findall('dnsrecords/dnsrecord')
|
|
|
|
|
|
|
|
|
|
DNS.createDNSZone(domain, admin)
|
|
|
|
|
|
|
|
|
|
zone = DNS.getZoneObject(domain)
|
|
|
|
|
|
|
|
|
|
for dnsrecord in dnsrecords:
|
|
|
|
|
recordType = dnsrecord.find('type').text
|
|
|
|
|
value = dnsrecord.find('name').text
|
|
|
|
|
content = dnsrecord.find('content').text
|
|
|
|
|
prio = int(dnsrecord.find('priority').text)
|
|
|
|
|
|
|
|
|
|
DNS.createDNSRecord(zone, value, recordType, content, prio, 3600)
|
|
|
|
|
|
|
|
|
|
return 1, 'None'
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return 0, str(msg)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def startRestore(backupName, dir):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
if dir == "CyberPanelRestore":
|
|
|
|
|
backupFileName = backupName.strip(".tar.gz")
|
|
|
|
|
completPath = os.path.join("/home", "backup", backupFileName) ## without extension
|
|
|
|
|
originalFile = os.path.join("/home", "backup", backupName) ## with extension
|
|
|
|
|
elif dir == 'CLI':
|
|
|
|
|
completPath = backupName.strip(".tar.gz") ## without extension
|
|
|
|
|
originalFile = backupName ## with extension
|
|
|
|
|
else:
|
|
|
|
|
backupFileName = backupName.strip(".tar.gz")
|
|
|
|
|
completPath = "/home/backup/transfer-" + str(dir) + "/" + backupFileName ## without extension
|
|
|
|
|
originalFile = "/home/backup/transfer-" + str(dir) + "/" + backupName ## with extension
|
|
|
|
|
|
|
|
|
|
pathToCompressedHome = os.path.join(completPath, "public_html.tar.gz")
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(completPath):
|
|
|
|
|
os.mkdir(completPath)
|
|
|
|
|
|
|
|
|
|
## Writing pid of restore process
|
|
|
|
|
|
|
|
|
|
pid = os.path.join(completPath, 'pid')
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(pid, str(os.getpid()))
|
|
|
|
|
|
|
|
|
|
status = os.path.join(completPath, 'status')
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Extracting Main Archive!")
|
|
|
|
|
|
|
|
|
|
## Converting /home/backup/backup-example.com-02.13.2018_10-24-52.tar.gz -> /home/backup/backup-example.com-02.13.2018_10-24-52
|
|
|
|
|
|
|
|
|
|
tar = tarfile.open(originalFile)
|
|
|
|
|
tar.extractall(completPath)
|
|
|
|
|
tar.close()
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Creating Accounts,Databases and DNS records!")
|
|
|
|
|
|
|
|
|
|
########### Creating website and its dabases
|
|
|
|
|
|
|
|
|
|
## extracting master domain for later use
|
|
|
|
|
backupMetaData = ElementTree.parse(os.path.join(completPath, "meta.xml"))
|
|
|
|
|
masterDomain = backupMetaData.find('masterDomain').text
|
|
|
|
|
VERSION = backupMetaData.find('VERSION').text
|
|
|
|
|
BUILD = backupMetaData.find('BUILD').text
|
|
|
|
|
|
|
|
|
|
twoPointO = 0
|
|
|
|
|
try:
|
|
|
|
|
version = backupMetaData.find('VERSION').text
|
|
|
|
|
build = backupMetaData.find('BUILD').text
|
|
|
|
|
phpSelectionGlobalMainSite = backupMetaData.find('phpSelection').text
|
|
|
|
|
twoPointO = 1
|
|
|
|
|
except:
|
|
|
|
|
twoPointO = 0
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
BackupWholeDir = int(backupMetaData.find('BackupWholeDir').text)
|
|
|
|
|
except:
|
|
|
|
|
BackupWholeDir = 0
|
|
|
|
|
|
|
|
|
|
result = backupUtilities.createWebsiteFromBackup(backupName, dir)
|
|
|
|
|
|
|
|
|
|
if result[0] == 1:
|
|
|
|
|
## Let us try to restore SSL.
|
|
|
|
|
|
|
|
|
|
sslStoragePath = completPath + "/" + masterDomain + ".cert.pem"
|
|
|
|
|
|
|
|
|
|
if os.path.exists(sslStoragePath):
|
|
|
|
|
sslHome = '/etc/letsencrypt/live/' + masterDomain
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if not os.path.exists(sslHome):
|
|
|
|
|
os.mkdir(sslHome)
|
|
|
|
|
|
|
|
|
|
copy(completPath + "/" + masterDomain + ".cert.pem", sslHome + "/cert.pem")
|
|
|
|
|
copy(completPath + "/" + masterDomain + ".privkey.pem", sslHome + "/privkey.pem")
|
|
|
|
|
copy(completPath + "/" + masterDomain + ".fullchain.pem", sslHome + "/fullchain.pem")
|
|
|
|
|
|
|
|
|
|
sslUtilities.installSSLForDomain(masterDomain)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s. [555:startRestore]' % (str(msg)))
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Error Message: " + result[
|
|
|
|
|
1] + ". Not able to create Account, Databases and DNS Records, aborting. [575][5009]")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
#### Find out web server from backup conf
|
|
|
|
|
|
|
|
|
|
CurrentServer = ProcessUtilities.OLS
|
|
|
|
|
|
|
|
|
|
if os.path.exists(completPath + '/vhost.conf'):
|
|
|
|
|
if open(f'{completPath}/vhost.conf', 'r').read().find('ServerName') > -1:
|
|
|
|
|
CurrentServer = ProcessUtilities.ent
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
########### Creating child/sub/addon/parked domains
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Creating Child Domains!")
|
|
|
|
|
|
|
|
|
|
## Reading meta file to create subdomains
|
|
|
|
|
|
|
|
|
|
externalApp = backupMetaData.find('externalApp').text
|
|
|
|
|
websiteHome = os.path.join("/home", masterDomain, "public_html")
|
|
|
|
|
|
|
|
|
|
### Restoring Child Domains if any.
|
|
|
|
|
|
|
|
|
|
childDomains = backupMetaData.findall('ChildDomains/domain')
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
for childDomain in childDomains:
|
|
|
|
|
|
|
|
|
|
domain = childDomain.find('domain').text
|
|
|
|
|
|
|
|
|
|
## mail domain check
|
|
|
|
|
|
|
|
|
|
mailDomain = 'mail.%s' % (masterDomain)
|
|
|
|
|
|
|
|
|
|
if domain == mailDomain:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
## Mail domain check
|
|
|
|
|
|
|
|
|
|
phpSelection = childDomain.find('phpSelection').text
|
|
|
|
|
path = childDomain.find('path').text
|
|
|
|
|
|
|
|
|
|
retValues = virtualHostUtilities.createDomain(masterDomain, domain, phpSelection, path, 0, 0, 0,
|
|
|
|
|
'admin', 0)
|
|
|
|
|
|
|
|
|
|
if retValues[0] == 1:
|
|
|
|
|
if os.path.exists(websiteHome):
|
|
|
|
|
rmtree(websiteHome)
|
|
|
|
|
|
|
|
|
|
## Let us try to restore SSL for Child Domains.
|
|
|
|
|
from ApachController.ApacheController import ApacheController
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
if os.path.exists(completPath + '/' + domain + '.vhost.conf'):
|
|
|
|
|
|
|
|
|
|
if CurrentServer == ProcessUtilities.decideServer():
|
|
|
|
|
|
|
|
|
|
completPathToConf = backupUtilities.Server_root + '/conf/vhosts/' + domain + '/vhost.conf'
|
|
|
|
|
childConfPathinBKUP = completPath + '/' + domain + '.vhost.conf'
|
|
|
|
|
copy(childConfPathinBKUP, completPathToConf)
|
|
|
|
|
|
|
|
|
|
### take care of apache conf
|
|
|
|
|
|
|
|
|
|
url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission"
|
|
|
|
|
data = {
|
|
|
|
|
"name": "all",
|
|
|
|
|
"IP": ACLManager.GetServerIP()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
response = requests.post(url, data=json.dumps(data))
|
|
|
|
|
Status = response.json()['status']
|
|
|
|
|
|
|
|
|
|
if (Status == 1):
|
|
|
|
|
|
|
|
|
|
childConfPathinBKUPApache = completPath + '/' + domain + '.apache.conf'
|
|
|
|
|
tempStatusPath = '/home/cyberpanel/fakePath'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Conf path of apache for child domain {domain} in backup is {childConfPathinBKUPApache}')
|
|
|
|
|
|
|
|
|
|
childData = open(childConfPathinBKUP, 'r').read()
|
|
|
|
|
|
|
|
|
|
if childData.find('proxyApacheBackendSSL') > -1 and os.path.exists(childConfPathinBKUPApache):
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'It seems child domain {domain} is using apache conf and {childConfPathinBKUPApache} also exists in backup file')
|
|
|
|
|
|
|
|
|
|
virtualHostUtilities.switchServer(domain, phpSelection, virtualHostUtilities.apache, tempStatusPath)
|
|
|
|
|
|
|
|
|
|
finalConfPathApache = ApacheVhost.configBasePath + domain + '.conf'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if os.path.exists(finalConfPathApache):
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'CyberPanel was able to successfully convert {domain} to apache conf as {finalConfPathApache} exists..')
|
|
|
|
|
|
|
|
|
|
copy(childConfPathinBKUPApache, finalConfPathApache)
|
|
|
|
|
|
|
|
|
|
### apache ends
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sslStoragePath = completPath + "/" + domain + ".cert.pem"
|
|
|
|
|
|
|
|
|
|
if os.path.exists(sslStoragePath):
|
|
|
|
|
sslHome = '/etc/letsencrypt/live/' + domain
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if not os.path.exists(sslHome):
|
|
|
|
|
os.mkdir(sslHome)
|
|
|
|
|
|
|
|
|
|
copy(completPath + "/" + domain + ".cert.pem", sslHome + "/cert.pem")
|
|
|
|
|
copy(completPath + "/" + domain + ".privkey.pem", sslHome + "/privkey.pem")
|
|
|
|
|
copy(completPath + "/" + domain + ".fullchain.pem",
|
|
|
|
|
sslHome + "/fullchain.pem")
|
|
|
|
|
|
|
|
|
|
sslUtilities.installSSLForDomain(domain)
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
except:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'While restoring backup we had minor issues for rebuilding vhost conf for: ' + domain + '. However this will be auto healed.')
|
|
|
|
|
|
|
|
|
|
if float(version) > 2.0 or float(build) > 0:
|
|
|
|
|
if path.find('/home/%s/public_html' % masterDomain) == -1:
|
|
|
|
|
|
|
|
|
|
if BackupWholeDir == 0:
|
|
|
|
|
|
|
|
|
|
#copy_tree('%s/%s-docroot' % (completPath, domain), path)
|
|
|
|
|
|
|
|
|
|
## First remove if already exists
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf %s' % (path)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
command = 'cp -R %s/%s-docroot %s' % (completPath, domain, path)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Error domain %s' % (domain))
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Error Message: " + retValues[
|
|
|
|
|
1] + ". Not able to create child domains, aborting. [635][5009]")
|
|
|
|
|
return 0
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
status = open(os.path.join(completPath, 'status'), "w")
|
|
|
|
|
status.write("Error Message: " + str(msg) + ". Not able to create child domains, aborting. [638][5009]")
|
|
|
|
|
status.close()
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [startRestore]")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
## Restore Aliases
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Restoring Domain Aliases!")
|
|
|
|
|
|
|
|
|
|
aliases = backupMetaData.findall('Aliases/alias')
|
|
|
|
|
|
|
|
|
|
for items in aliases:
|
|
|
|
|
virtualHostUtilities.createAlias(masterDomain, items.text, 0, "", "", "admin")
|
|
|
|
|
|
|
|
|
|
## Restoring email accounts
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Restoring email accounts!")
|
|
|
|
|
|
|
|
|
|
emailAccounts = backupMetaData.findall('emails/emailAccount')
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
for emailAccount in emailAccounts:
|
|
|
|
|
|
|
|
|
|
email = emailAccount.find('email').text
|
|
|
|
|
username = email.split("@")[0]
|
|
|
|
|
password = emailAccount.find('password').text
|
|
|
|
|
|
|
|
|
|
result = mailUtilities.createEmailAccount(masterDomain, username, password, 'restore')
|
|
|
|
|
if result[0] == 0:
|
|
|
|
|
raise BaseException(result[1])
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Error Message: " + str(
|
|
|
|
|
msg) + ". Not able to create email accounts, aborting. [671][5009]")
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [startRestore]")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
## Emails restored
|
|
|
|
|
|
|
|
|
|
## restoring databases
|
|
|
|
|
|
|
|
|
|
### This will actually restore mysql dump and create mysql users
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Restoring Databases!")
|
|
|
|
|
|
|
|
|
|
databases = backupMetaData.findall('Databases/database')
|
|
|
|
|
|
|
|
|
|
for database in databases:
|
|
|
|
|
|
|
|
|
|
dbName = database.find('dbName').text
|
|
|
|
|
|
|
|
|
|
if ((VERSION == '2.1' or VERSION == '2.3') and int(BUILD) >= 1) or (VERSION == '2.4' and int(BUILD) >= 0):
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Backup version 2.1.1+ detected..')
|
|
|
|
|
|
|
|
|
|
first = 1
|
|
|
|
|
|
|
|
|
|
databaseUsers = database.findall('databaseUsers')
|
|
|
|
|
|
|
|
|
|
for databaseUser in databaseUsers:
|
|
|
|
|
|
|
|
|
|
dbUser = databaseUser.find('dbUser').text
|
|
|
|
|
dbHost = databaseUser.find('dbHost').text
|
|
|
|
|
password = databaseUser.find('password').text
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Database user: %s' % (dbUser))
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Database host: %s' % (dbHost))
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Database password: %s' % (password))
|
|
|
|
|
|
|
|
|
|
## Future ref, this logic can be further refactored to improve restore backup logic
|
|
|
|
|
if first:
|
|
|
|
|
first = 0
|
|
|
|
|
res = mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(dbName, completPath, password, 1)
|
|
|
|
|
if res == 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'Failed to restore database %s. But it can be false positive, moving on..' % (
|
|
|
|
|
dbName))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### This function will not create database, only database user is created as third value is 0 for createDB
|
|
|
|
|
|
|
|
|
|
mysqlUtilities.mysqlUtilities.createDatabase(dbName, dbUser, password, 0, dbHost)
|
|
|
|
|
mysqlUtilities.mysqlUtilities.changePassword(dbUser, password, 1, dbHost)
|
|
|
|
|
|
|
|
|
|
# UserInMySQLTable = DBUsers.objects.get(user=dbUser, host=dbHost)
|
|
|
|
|
# UserInMySQLTable.password = password
|
|
|
|
|
# UserInMySQLTable.save()
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
password = database.find('password').text
|
|
|
|
|
if mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(dbName, completPath, password) == 0:
|
|
|
|
|
raise BaseException
|
|
|
|
|
|
|
|
|
|
## Databases restored
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Extracting web home data!")
|
|
|
|
|
|
|
|
|
|
# /home/backup/backup-example.com-02.13.2018_10-24-52/public_html.tar.gz
|
|
|
|
|
## Moving above v2.0.0 extracting webhome data is not required, thus commenting below lines
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not twoPointO:
|
|
|
|
|
tar = tarfile.open(pathToCompressedHome)
|
|
|
|
|
tar.extractall(websiteHome)
|
|
|
|
|
tar.close()
|
|
|
|
|
else:
|
|
|
|
|
if float(version) > 2.0 or float(build) > 0:
|
|
|
|
|
#copy_tree('%s/public_html' % (completPath), websiteHome)
|
|
|
|
|
|
|
|
|
|
## First remove if already exists
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf %s' % (websiteHome)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
if BackupWholeDir:
|
|
|
|
|
#command = 'cp -R %s/public_html/* %s/*' % (completPath, websiteHome)
|
|
|
|
|
command = f'rsync -av {completPath}/public_html/ /home/{masterDomain}'
|
|
|
|
|
else:
|
|
|
|
|
command = 'cp -R %s/public_html %s' % (completPath, websiteHome)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
## extracting email accounts
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Extracting email accounts!")
|
|
|
|
|
|
|
|
|
|
if not twoPointO:
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
pathToCompressedEmails = os.path.join(completPath, masterDomain + ".tar.gz")
|
|
|
|
|
emailHome = os.path.join("/home", "vmail", masterDomain)
|
|
|
|
|
|
|
|
|
|
tar = tarfile.open(pathToCompressedEmails)
|
|
|
|
|
tar.extractall(emailHome)
|
|
|
|
|
tar.close()
|
|
|
|
|
|
|
|
|
|
## Change permissions
|
|
|
|
|
|
|
|
|
|
command = "chown -R vmail:vmail " + emailHome
|
|
|
|
|
subprocess.call(shlex.split(command))
|
|
|
|
|
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
emailsPath = '%s/vmail' % (completPath)
|
|
|
|
|
|
|
|
|
|
if os.path.exists(emailsPath):
|
|
|
|
|
#copy_tree(emailsPath, '/home/vmail/%s' % (masterDomain))
|
|
|
|
|
|
|
|
|
|
## First remove if already exists
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf /home/vmail/%s' % (masterDomain)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
command = 'cp -R %s /home/vmail/%s' % (emailsPath, masterDomain)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = "chown -R vmail:vmail /home/vmail/%s" % (masterDomain)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
## emails extracted
|
|
|
|
|
|
|
|
|
|
completPathToConf = backupUtilities.Server_root + '/conf/vhosts/' + masterDomain + '/vhost.conf'
|
|
|
|
|
if os.path.exists(completPath + '/vhost.conf'):
|
|
|
|
|
if CurrentServer == ProcessUtilities.decideServer():
|
|
|
|
|
confPathMainSite = completPath + '/vhost.conf'
|
|
|
|
|
copy(confPathMainSite, completPathToConf)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### apache starts here
|
|
|
|
|
|
|
|
|
|
url = "https://platform.cyberpersons.com/CyberpanelAdOns/Adonpermission"
|
|
|
|
|
data = {
|
|
|
|
|
"name": "all",
|
|
|
|
|
"IP": ACLManager.GetServerIP()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
response = requests.post(url, data=json.dumps(data))
|
|
|
|
|
Status = response.json()['status']
|
|
|
|
|
|
|
|
|
|
if (Status == 1):
|
|
|
|
|
confPathApache = completPath + '/apache.conf'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f'Conf path of apache for main site {masterDomain} in backup is {confPathApache}')
|
|
|
|
|
|
|
|
|
|
tempStatusPath = '/home/cyberpanel/fakePath'
|
|
|
|
|
|
|
|
|
|
childData = open(confPathMainSite, 'r').read()
|
|
|
|
|
|
|
|
|
|
if childData.find('proxyApacheBackendSSL') > -1 and os.path.exists(confPathApache):
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'It seems main site {masterDomain} is using apache conf.')
|
|
|
|
|
|
|
|
|
|
virtualHostUtilities.switchServer(masterDomain, phpSelectionGlobalMainSite, virtualHostUtilities.apache,
|
|
|
|
|
tempStatusPath)
|
|
|
|
|
|
|
|
|
|
finalConfPathApache = ApacheVhost.configBasePath + masterDomain + '.conf'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'Apache conf path of main domain exists which means CyberPanel successfully converted site to Apache for {masterDomain}')
|
|
|
|
|
|
|
|
|
|
if os.path.exists(confPathApache):
|
|
|
|
|
copy(confPathApache, finalConfPathApache)
|
|
|
|
|
|
|
|
|
|
### apache ends here
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, "Done")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Fix permissions
|
|
|
|
|
|
|
|
|
|
from filemanager.filemanager import FileManager
|
|
|
|
|
|
|
|
|
|
fm = FileManager(None, None)
|
|
|
|
|
fm.fixPermissions(masterDomain)
|
|
|
|
|
|
|
|
|
|
installUtilities.reStartLiteSpeed()
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
status = os.path.join(completPath, 'status')
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(status, str(msg) + " [736][5009]")
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [startRestore]")
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def initiateRestore(backupName, dir):
|
|
|
|
|
try:
|
|
|
|
|
p = Process(target=backupUtilities.startRestore, args=(backupName, dir,))
|
|
|
|
|
p.start()
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [initiateRestore]")
|
|
|
|
|
|
|
|
|
|
# @staticmethod
|
|
|
|
|
# def sendKey(IPAddress, password, port='22', user='root'):
|
|
|
|
|
# try:
|
|
|
|
|
#
|
|
|
|
|
# expectation = []
|
|
|
|
|
# expectation.append("password:")
|
|
|
|
|
# expectation.append("Password:")
|
|
|
|
|
# expectation.append("Permission denied")
|
|
|
|
|
# expectation.append("100%")
|
|
|
|
|
#
|
|
|
|
|
# ## Temp changes
|
|
|
|
|
#
|
|
|
|
|
# command = 'chmod 600 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
# ProcessUtilities.executioner(command)
|
|
|
|
|
#
|
|
|
|
|
# command = "scp -o StrictHostKeyChecking=no -P " + port + " /root/.ssh/cyberpanel.pub " + user + "@" + IPAddress + ":~/.ssh/authorized_keys"
|
|
|
|
|
# setupKeys = pexpect.spawn(command, timeout=3)
|
|
|
|
|
#
|
|
|
|
|
# if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
# logging.CyberCPLogFileWriter.writeToFile(command)
|
|
|
|
|
#
|
|
|
|
|
# index = setupKeys.expect(expectation)
|
|
|
|
|
#
|
|
|
|
|
# ## on first login attempt send password
|
|
|
|
|
#
|
|
|
|
|
# if index == 0:
|
|
|
|
|
# setupKeys.sendline(password)
|
|
|
|
|
# setupKeys.expect("100%")
|
|
|
|
|
# setupKeys.wait()
|
|
|
|
|
# elif index == 1:
|
|
|
|
|
# setupKeys.sendline(password)
|
|
|
|
|
# setupKeys.expect("100%")
|
|
|
|
|
# setupKeys.wait()
|
|
|
|
|
# elif index == 2:
|
|
|
|
|
# return [0, 'Please enable password authentication on your remote server.']
|
|
|
|
|
# elif index == 3:
|
|
|
|
|
# pass
|
|
|
|
|
# else:
|
|
|
|
|
# raise BaseException
|
|
|
|
|
#
|
|
|
|
|
# ## Temp changes
|
|
|
|
|
#
|
|
|
|
|
# command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
# ProcessUtilities.executioner(command)
|
|
|
|
|
#
|
|
|
|
|
# return [1, "None"]
|
|
|
|
|
#
|
|
|
|
|
# except pexpect.TIMEOUT as msg:
|
|
|
|
|
#
|
|
|
|
|
# command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
# ProcessUtilities.executioner(command)
|
|
|
|
|
#
|
|
|
|
|
# logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [sendKey]")
|
|
|
|
|
# return [0, "TIMEOUT [sendKey]"]
|
|
|
|
|
# except pexpect.EOF as msg:
|
|
|
|
|
#
|
|
|
|
|
# command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
# ProcessUtilities.executioner(command)
|
|
|
|
|
#
|
|
|
|
|
# logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [sendKey]")
|
|
|
|
|
# return [0, "EOF [sendKey]"]
|
|
|
|
|
# except BaseException as msg:
|
|
|
|
|
#
|
|
|
|
|
# command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
# ProcessUtilities.executioner(command)
|
|
|
|
|
#
|
|
|
|
|
# logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [sendKey]")
|
|
|
|
|
# return [0, str(msg) + " [sendKey]"]
|
|
|
|
|
|
|
|
|
|
# @staticmethod
|
|
|
|
|
# def setupSSHKeys(IPAddress, password, port='22', user='root'):
|
|
|
|
|
# try:
|
|
|
|
|
# ## Checking for host verification
|
|
|
|
|
#
|
|
|
|
|
# backupUtilities.host_key_verification(IPAddress)
|
|
|
|
|
#
|
|
|
|
|
# if backupUtilities.checkIfHostIsUp(IPAddress) == 1:
|
|
|
|
|
# pass
|
|
|
|
|
# else:
|
|
|
|
|
# logging.CyberCPLogFileWriter.writeToFile("Host is Down.")
|
|
|
|
|
# # return [0,"Host is Down."]
|
|
|
|
|
#
|
|
|
|
|
# expectation = []
|
|
|
|
|
# expectation.append("password:")
|
|
|
|
|
# expectation.append("Password:")
|
|
|
|
|
# expectation.append("Permission denied")
|
|
|
|
|
# expectation.append("File exists")
|
|
|
|
|
#
|
|
|
|
|
# command = "ssh -o StrictHostKeyChecking=no -p " + port + ' ' + user + "@" + IPAddress + ' "mkdir ~/.ssh || rm -f ~/.ssh/temp && rm -f ~/.ssh/authorized_temp && cp ~/.ssh/authorized_keys ~/.ssh/temp || chmod 700 ~/.ssh || chmod g-w ~"'
|
|
|
|
|
# setupKeys = pexpect.spawn(command, timeout=3)
|
|
|
|
|
#
|
|
|
|
|
# if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
# logging.CyberCPLogFileWriter.writeToFile(command)
|
|
|
|
|
#
|
|
|
|
|
# index = setupKeys.expect(expectation)
|
|
|
|
|
#
|
|
|
|
|
# ## on first login attempt send password
|
|
|
|
|
#
|
|
|
|
|
# if index == 0:
|
|
|
|
|
# setupKeys.sendline(password)
|
|
|
|
|
# elif index == 1:
|
|
|
|
|
# setupKeys.sendline(password)
|
|
|
|
|
# elif index == 2:
|
|
|
|
|
# return [0, 'Please enable password authentication on your remote server.']
|
|
|
|
|
# elif index == 3:
|
|
|
|
|
# pass
|
|
|
|
|
# else:
|
|
|
|
|
# raise BaseException
|
|
|
|
|
#
|
|
|
|
|
# ## if it again give you password, than provided password is wrong
|
|
|
|
|
#
|
|
|
|
|
# expectation = []
|
|
|
|
|
# expectation.append("please try again.")
|
|
|
|
|
# expectation.append("Password:")
|
|
|
|
|
# expectation.append(pexpect.EOF)
|
|
|
|
|
#
|
|
|
|
|
# index = setupKeys.expect(expectation)
|
|
|
|
|
#
|
|
|
|
|
# if index == 0:
|
|
|
|
|
# return [0, "Wrong Password!"]
|
|
|
|
|
# elif index == 1:
|
|
|
|
|
# return [0, "Wrong Password!"]
|
|
|
|
|
# elif index == 2:
|
|
|
|
|
# setupKeys.wait()
|
|
|
|
|
#
|
|
|
|
|
# sendKey = backupUtilities.sendKey(IPAddress, password, port, user)
|
|
|
|
|
#
|
|
|
|
|
# if sendKey[0] == 1:
|
|
|
|
|
# return [1, "None"]
|
|
|
|
|
# else:
|
|
|
|
|
# return [0, sendKey[1]]
|
|
|
|
|
#
|
|
|
|
|
#
|
|
|
|
|
# except pexpect.TIMEOUT as msg:
|
|
|
|
|
# return [0, str(msg) + " [TIMEOUT setupSSHKeys]"]
|
|
|
|
|
# except BaseException as msg:
|
|
|
|
|
# return [0, str(msg) + " [setupSSHKeys]"]
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def sendKey(IPAddress, password, port='22', user='root'):
|
|
|
|
|
try:
|
|
|
|
|
ssh = paramiko.SSHClient()
|
|
|
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
|
ssh.connect(IPAddress, port=int(port), username=user, password=password)
|
|
|
|
|
|
|
|
|
|
if os.path.exists('/root/.ssh/cyberpanel.pub'):
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
command = "ssh-keygen -f /root/.ssh/cyberpanel -t rsa -N ''"
|
|
|
|
|
ProcessUtilities.executioner(command, 'root', True)
|
|
|
|
|
|
|
|
|
|
command = 'chmod 600 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Try to use SFTP to create .ssh directory if it doesn't exist
|
|
|
|
|
sftp = ssh.open_sftp()
|
|
|
|
|
try:
|
|
|
|
|
sftp.stat('.ssh')
|
|
|
|
|
except FileNotFoundError:
|
|
|
|
|
# Try to create .ssh directory via SFTP
|
|
|
|
|
try:
|
|
|
|
|
sftp.mkdir('.ssh')
|
|
|
|
|
except:
|
|
|
|
|
# Directory creation via SFTP might fail on some servers
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# Try to upload the key
|
|
|
|
|
sftp.put('/root/.ssh/cyberpanel.pub', '.ssh/authorized_keys')
|
|
|
|
|
sftp.close()
|
|
|
|
|
|
|
|
|
|
# Try to set permissions via SSH command (might fail on SFTP-only servers)
|
|
|
|
|
try:
|
|
|
|
|
stdin, stdout, stderr = ssh.exec_command('chmod 600 .ssh/authorized_keys', timeout=5)
|
|
|
|
|
stdout.channel.recv_exit_status()
|
|
|
|
|
except:
|
|
|
|
|
# If chmod fails, it's likely an SFTP-only server
|
|
|
|
|
# The key is uploaded, which is what matters for backups using password auth
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'Could not set permissions on {IPAddress}, likely SFTP-only server')
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
# If we can't upload the key, it might be an SFTP-only server
|
|
|
|
|
# Return success anyway since password authentication works
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'Could not upload SSH key to {IPAddress}: {str(e)}, using password authentication')
|
|
|
|
|
ssh.close()
|
|
|
|
|
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
|
|
|
|
|
ssh.close()
|
|
|
|
|
|
|
|
|
|
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except paramiko.AuthenticationException:
|
|
|
|
|
return [0, 'Authentication failed. [sendKey]']
|
|
|
|
|
except paramiko.SSHException as e:
|
|
|
|
|
return [0, f'SSH error: {str(e)} [sendKey]']
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return [0, f'General Error: {str(e)} [sendKey]']
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def setupSSHKeys(IPAddress, password, port='22', user='root'):
|
|
|
|
|
try:
|
|
|
|
|
ssh = paramiko.SSHClient()
|
|
|
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
|
if password != 'NOT-NEEDED':
|
|
|
|
|
|
|
|
|
|
ssh.connect(IPAddress, port=int(port), username=user, password=password)
|
|
|
|
|
|
|
|
|
|
# Try to execute SSH commands first
|
|
|
|
|
ssh_commands_supported = True
|
|
|
|
|
commands = [
|
|
|
|
|
"mkdir -p .ssh",
|
|
|
|
|
"rm -f .ssh/temp",
|
|
|
|
|
"rm -f .ssh/authorized_temp",
|
|
|
|
|
"cp .ssh/authorized_keys .ssh/temp",
|
|
|
|
|
"chmod 700 .ssh",
|
|
|
|
|
"chmod g-w ~",
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for command in commands:
|
|
|
|
|
try:
|
|
|
|
|
stdin, stdout, stderr = ssh.exec_command(command, timeout=5)
|
|
|
|
|
exit_status = stdout.channel.recv_exit_status()
|
|
|
|
|
error_output = stderr.read().decode()
|
|
|
|
|
|
|
|
|
|
# Check if the command was rejected (SFTP-only server)
|
|
|
|
|
if exit_status != 0 or "not allowed" in error_output.lower() or "channel closed" in error_output.lower():
|
|
|
|
|
ssh_commands_supported = False
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'SSH commands not supported on {IPAddress}, falling back to pure SFTP mode')
|
|
|
|
|
break
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
ssh_commands_supported = False
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'Error executing remote command {command}. Error {str(msg)}, falling back to pure SFTP mode')
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
ssh.close()
|
|
|
|
|
|
|
|
|
|
# If SSH commands are not supported, use pure SFTP mode
|
|
|
|
|
if not ssh_commands_supported:
|
|
|
|
|
# For SFTP-only servers, we'll use password authentication directly
|
|
|
|
|
# No need to setup SSH keys, just verify connection works
|
|
|
|
|
try:
|
|
|
|
|
test_ssh = paramiko.SSHClient()
|
|
|
|
|
test_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
|
test_ssh.connect(IPAddress, port=int(port), username=user, password=password)
|
|
|
|
|
|
|
|
|
|
# Open SFTP connection to verify it works
|
|
|
|
|
sftp = test_ssh.open_sftp()
|
|
|
|
|
sftp.close()
|
|
|
|
|
test_ssh.close()
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f'Pure SFTP mode verified for {IPAddress}')
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return [0, f'SFTP connection failed: {str(e)}']
|
|
|
|
|
else:
|
|
|
|
|
# SSH commands are supported, proceed with key setup
|
|
|
|
|
sendKey = backupUtilities.sendKey(IPAddress, password, port, user)
|
|
|
|
|
|
|
|
|
|
if sendKey[0] == 1:
|
|
|
|
|
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
else:
|
|
|
|
|
command = 'chmod 644 %s' % ('/root/.ssh/cyberpanel.pub')
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
return [0, sendKey[1]]
|
|
|
|
|
else:
|
|
|
|
|
# Load the private key
|
|
|
|
|
private_key_path = '/root/.ssh/cyberpanel'
|
|
|
|
|
keyPrivate = paramiko.RSAKey(filename=private_key_path)
|
|
|
|
|
|
|
|
|
|
# Connect to the remote server using the private key
|
|
|
|
|
ssh = paramiko.SSHClient()
|
|
|
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
|
ssh.connect(IPAddress, username=user, pkey=keyPrivate)
|
|
|
|
|
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
|
|
|
|
|
except paramiko.AuthenticationException:
|
|
|
|
|
return [0, 'Authentication failed. [setupSSHKeys]']
|
|
|
|
|
except paramiko.SSHException as e:
|
|
|
|
|
return [0, f'SSH error: {str(e)} [setupSSHKeys]']
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return [0, f'General Error: {str(e)} [setupSSHKeys]']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def checkIfHostIsUp(IPAddress):
|
|
|
|
|
try:
|
|
|
|
|
if subprocess.check_output(['ping', IPAddress, '-c 1']).decode("utf-8").find("0% packet loss") > -1:
|
|
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
return 0
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + "[checkIfHostIsUp]")
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def checkConnection(IPAddress, port='22', user='root'):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
import json
|
|
|
|
|
destinations = backupUtilities.destinationsPath
|
|
|
|
|
data = json.loads(open(destinations, 'r').read())
|
|
|
|
|
port = data['port']
|
|
|
|
|
user = data['user']
|
|
|
|
|
except:
|
|
|
|
|
port = "22"
|
|
|
|
|
|
|
|
|
|
expectation = []
|
|
|
|
|
expectation.append("password:")
|
|
|
|
|
expectation.append("Password:")
|
|
|
|
|
expectation.append("Last login")
|
|
|
|
|
expectation.append(pexpect.EOF)
|
|
|
|
|
expectation.append(pexpect.TIMEOUT)
|
|
|
|
|
|
|
|
|
|
command = "sudo ssh -i /root/.ssh/cyberpanel -o StrictHostKeyChecking=no -p " + port + ' ' + user + "@" + IPAddress
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(command)
|
|
|
|
|
|
|
|
|
|
checkConn = pexpect.spawn(command,timeout=3)
|
|
|
|
|
index = checkConn.expect(expectation)
|
|
|
|
|
|
|
|
|
|
if index == 0:
|
|
|
|
|
subprocess.call(['kill', str(checkConn.pid)])
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
"Remote Server is not able to authenticate for transfer to initiate, IP Address:" + IPAddress)
|
|
|
|
|
return [0, "Remote Server is not able to authenticate for transfer to initiate."]
|
|
|
|
|
elif index == 1:
|
|
|
|
|
subprocess.call(['kill', str(checkConn.pid)])
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
"Remote Server is not able to authenticate for transfer to initiate, IP Address:" + IPAddress)
|
|
|
|
|
return [0, "Remote Server is not able to authenticate for transfer to initiate."]
|
|
|
|
|
elif index == 2:
|
|
|
|
|
subprocess.call(['kill', str(checkConn.pid)])
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
elif index == 4:
|
|
|
|
|
subprocess.call(['kill', str(checkConn.pid)])
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
else:
|
|
|
|
|
subprocess.call(['kill', str(checkConn.pid)])
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
|
|
|
|
|
except pexpect.TIMEOUT as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Timeout " + IPAddress + " [checkConnection]")
|
|
|
|
|
return [0, "371 Timeout while making connection to this server [checkConnection]"]
|
|
|
|
|
except pexpect.EOF as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile("EOF " + IPAddress + "[checkConnection]")
|
|
|
|
|
return [0, "374 Remote Server is not able to authenticate for transfer to initiate. [checkConnection]"]
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " " + IPAddress + " [checkConnection]")
|
|
|
|
|
return [0, "377 Remote Server is not able to authenticate for transfer to initiate. [checkConnection]"]
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def verifyHostKey(IPAddress, port='22', user='root'):
|
|
|
|
|
try:
|
|
|
|
|
backupUtilities.host_key_verification(IPAddress)
|
|
|
|
|
|
|
|
|
|
password = "hello" ## dumb password, not used anywhere.
|
|
|
|
|
|
|
|
|
|
expectation = []
|
|
|
|
|
|
|
|
|
|
expectation.append("continue connecting (yes/no)?")
|
|
|
|
|
expectation.append("password:")
|
|
|
|
|
|
|
|
|
|
setupSSHKeys = pexpect.spawn("ssh -p " + port + user + "@" + IPAddress, timeout=3)
|
|
|
|
|
|
|
|
|
|
index = setupSSHKeys.expect(expectation)
|
|
|
|
|
|
|
|
|
|
if index == 0:
|
|
|
|
|
setupSSHKeys.sendline("yes")
|
|
|
|
|
|
|
|
|
|
setupSSHKeys.expect("password:")
|
|
|
|
|
setupSSHKeys.sendline(password)
|
|
|
|
|
|
|
|
|
|
expectation = []
|
|
|
|
|
|
|
|
|
|
expectation.append("password:")
|
|
|
|
|
expectation.append(pexpect.EOF)
|
|
|
|
|
|
|
|
|
|
innerIndex = setupSSHKeys.expect(expectation)
|
|
|
|
|
|
|
|
|
|
if innerIndex == 0:
|
|
|
|
|
setupSSHKeys.kill(signal.SIGTERM)
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
elif innerIndex == 1:
|
|
|
|
|
setupSSHKeys.kill(signal.SIGTERM)
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
|
|
|
|
|
elif index == 1:
|
|
|
|
|
|
|
|
|
|
setupSSHKeys.expect("password:")
|
|
|
|
|
setupSSHKeys.sendline(password)
|
|
|
|
|
|
|
|
|
|
expectation = []
|
|
|
|
|
|
|
|
|
|
expectation.append("password:")
|
|
|
|
|
expectation.append(pexpect.EOF)
|
|
|
|
|
|
|
|
|
|
innerIndex = setupSSHKeys.expect(expectation)
|
|
|
|
|
|
|
|
|
|
if innerIndex == 0:
|
|
|
|
|
setupSSHKeys.kill(signal.SIGTERM)
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
elif innerIndex == 1:
|
|
|
|
|
setupSSHKeys.kill(signal.SIGTERM)
|
|
|
|
|
return [1, "None"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except pexpect.TIMEOUT as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile("Timeout [verifyHostKey]")
|
|
|
|
|
return [0, "Timeout [verifyHostKey]"]
|
|
|
|
|
except pexpect.EOF as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile("EOF [verifyHostKey]")
|
|
|
|
|
return [0, "EOF [verifyHostKey]"]
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [verifyHostKey]")
|
|
|
|
|
return [0, str(msg) + " [verifyHostKey]"]
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def createBackupDir(IPAddress, port='22', user='root'):
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# First try SSH command
|
|
|
|
|
command = "sudo ssh -o StrictHostKeyChecking=no -p " + port + " -i /root/.ssh/cyberpanel " + user + "@" + IPAddress + " mkdir ~/backup"
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(command)
|
|
|
|
|
|
|
|
|
|
result = subprocess.call(shlex.split(command))
|
|
|
|
|
|
|
|
|
|
# If SSH command fails, it might be an SFTP-only server
|
|
|
|
|
if result != 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f"SSH command failed for {IPAddress}, likely SFTP-only server. Skipping directory creation.")
|
|
|
|
|
# Don't fail - SFTP servers may have their own directory structure
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
command = "sudo ssh -o StrictHostKeyChecking=no -p " + port + " -i /root/.ssh/cyberpanel " + user + "@" + IPAddress + ' "cat ~/.ssh/authorized_keys ~/.ssh/temp > ~/.ssh/authorized_temp"'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(command)
|
|
|
|
|
|
|
|
|
|
subprocess.call(shlex.split(command))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command = "sudo ssh -o StrictHostKeyChecking=no -p " + port + " -i /root/.ssh/cyberpanel " + user + "@" + IPAddress + ' "cat ~/.ssh/authorized_temp > ~/.ssh/authorized_keys"'
|
|
|
|
|
|
|
|
|
|
if os.path.exists(ProcessUtilities.debugPath):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(command)
|
|
|
|
|
|
|
|
|
|
subprocess.call(shlex.split(command))
|
|
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [createBackupDir]")
|
|
|
|
|
# Don't fail for SFTP-only servers
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def host_key_verification(IPAddress):
|
|
|
|
|
try:
|
|
|
|
|
command = 'sudo ssh-keygen -R ' + IPAddress
|
|
|
|
|
subprocess.call(shlex.split(command))
|
|
|
|
|
return 1
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [host_key_verification]")
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def getAliases(masterDomain):
|
|
|
|
|
try:
|
|
|
|
|
aliases = []
|
|
|
|
|
master = Websites.objects.get(domain=masterDomain)
|
|
|
|
|
aliasDomains = master.aliasdomains_set.all()
|
|
|
|
|
|
|
|
|
|
for items in aliasDomains:
|
|
|
|
|
aliases.append(items.aliasDomain)
|
|
|
|
|
|
|
|
|
|
return aliases
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(str(msg) + " [getAliases]")
|
|
|
|
|
print(0)
|
|
|
|
|
|
|
|
|
|
### Cloud Backup functions
|
|
|
|
|
|
|
|
|
|
def CheckIfSleepNeeded(self):
|
|
|
|
|
import psutil
|
|
|
|
|
while (1):
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Current CPU percent %s.' % (int(psutil.cpu_percent(interval=None))))
|
|
|
|
|
if int(psutil.cpu_percent(interval=None)) > int(self.cpu):
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Current CPU usage exceeds %s percent. Backup process will sleep for %s seconds..,0' % (self.cpu, str(self.time)))
|
|
|
|
|
import time
|
|
|
|
|
time.sleep(self.time)
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
def BackupData(self):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
### Creating the dir to store backups
|
|
|
|
|
self.BackupDataPath = '%s/data' % (self.BackupPath)
|
|
|
|
|
command = 'mkdir -p %s' % (self.BackupDataPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
self.DataPath = '/home/%s' % (self.extraArgs['domain'])
|
|
|
|
|
|
|
|
|
|
## Backing up data
|
|
|
|
|
|
|
|
|
|
self.CheckIfSleepNeeded()
|
|
|
|
|
|
|
|
|
|
command = 'nice -n %s cp -Rp %s %s' % (self.nice, self.DataPath, self.BackupDataPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
## Store child domains if any in json format
|
|
|
|
|
|
|
|
|
|
DataJson = {}
|
|
|
|
|
childs = []
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
for child in self.website.childdomains_set.all():
|
|
|
|
|
childs.append({'domain': child.domain, 'path': child.path, 'php': child.phpSelection})
|
|
|
|
|
|
|
|
|
|
DataJson['ChildDomains'] = childs
|
|
|
|
|
|
|
|
|
|
DataJsonPath = '%s/%s' % (self.BackupPath, 'data.json')
|
|
|
|
|
|
|
|
|
|
writeToFile = open(DataJsonPath, 'w')
|
|
|
|
|
writeToFile.write(json.dumps(DataJson))
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
return 1, None
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return 0, str(msg)
|
|
|
|
|
|
|
|
|
|
def BackupEmails(self):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
from mailServer.models import Domains, EUsers
|
|
|
|
|
try:
|
|
|
|
|
emailDomain = Domains.objects.get(domainOwner=self.website)
|
|
|
|
|
except:
|
|
|
|
|
return 1, None
|
|
|
|
|
|
|
|
|
|
### Creating the dir to store backups
|
|
|
|
|
self.BackupDataPath = '%s/emails' % (self.BackupPath)
|
|
|
|
|
command = 'mkdir -p %s' % (self.BackupDataPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
self.DataPath = '/home/vmail/%s' % (self.extraArgs['domain'])
|
|
|
|
|
|
|
|
|
|
## Backing up data
|
|
|
|
|
|
|
|
|
|
self.CheckIfSleepNeeded()
|
|
|
|
|
|
|
|
|
|
command = 'nice -n %s cp -Rp %s %s' % (self.nice, self.DataPath, self.BackupDataPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
## Store child domains if any in json format
|
|
|
|
|
|
|
|
|
|
DataJson = {}
|
|
|
|
|
emailsList = []
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
for emails in emailDomain.eusers_set.all():
|
|
|
|
|
emailsList.append({'email': emails.email, 'password': emails.password})
|
|
|
|
|
|
|
|
|
|
DataJson['emails'] = emailsList
|
|
|
|
|
DataJsonPath = '%s/%s' % (self.BackupPath, 'emails.json')
|
|
|
|
|
writeToFile = open(DataJsonPath, 'w')
|
|
|
|
|
writeToFile.write(json.dumps(DataJson))
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
return 1, None
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return 0, str(msg)
|
|
|
|
|
|
|
|
|
|
def BackupDatabases(self):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
### Creating the dir to store backups
|
|
|
|
|
self.BackupDataPath = '%s/databases' % (self.BackupPath)
|
|
|
|
|
command = 'mkdir -p %s' % (self.BackupDataPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
## Backing up data
|
|
|
|
|
|
|
|
|
|
self.CheckIfSleepNeeded()
|
|
|
|
|
DataJson = {}
|
|
|
|
|
databases = []
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
for items in self.website.databases_set.all():
|
|
|
|
|
try:
|
|
|
|
|
dbuser = DBUsers.objects.get(user=items.dbUser)
|
|
|
|
|
userToTry = items.dbUser
|
|
|
|
|
except:
|
|
|
|
|
try:
|
|
|
|
|
dbusers = DBUsers.objects.all().filter(user=items.dbUser)
|
|
|
|
|
userToTry = items.dbUser
|
|
|
|
|
for it in dbusers:
|
|
|
|
|
dbuser = it
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
userToTry = mysqlUtilities.mysqlUtilities.fetchuser(items.dbName)
|
|
|
|
|
|
|
|
|
|
if userToTry == 0 or userToTry == 1:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
dbuser = DBUsers.objects.get(user=userToTry)
|
|
|
|
|
except:
|
|
|
|
|
try:
|
|
|
|
|
dbusers = DBUsers.objects.all().filter(user=userToTry)
|
|
|
|
|
for it in dbusers:
|
|
|
|
|
dbuser = it
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'While creating backup for %s, we failed to backup database %s. Error message: %s' % (
|
|
|
|
|
self.website.domain, items.dbName, str(msg)))
|
|
|
|
|
continue
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
'While creating backup for %s, we failed to backup database %s. Error message: %s' % (
|
|
|
|
|
self.website.domain, items.dbName, str(msg)))
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
databases.append({'databaseName': str(items.dbName), 'databaseUser': str(userToTry), 'password': str(dbuser.password)})
|
|
|
|
|
self.CheckIfSleepNeeded()
|
|
|
|
|
mysqlUtilities.mysqlUtilities.createDatabaseBackup(items.dbName, self.BackupDataPath)
|
|
|
|
|
|
|
|
|
|
DataJson['databases'] = databases
|
|
|
|
|
DataJsonPath = '%s/%s' % (self.BackupPath, 'databases.json')
|
|
|
|
|
|
|
|
|
|
writeToFile = open(DataJsonPath, 'w')
|
|
|
|
|
writeToFile.write(json.dumps(DataJson))
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
|
|
|
|
|
return 1, None
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
return 0, str(msg)
|
|
|
|
|
|
|
|
|
|
def CloudBackups(self):
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
if os.path.exists(backupUtilities.CloudBackupConfigPath):
|
|
|
|
|
result = json.loads(open(backupUtilities.CloudBackupConfigPath, 'r').read())
|
|
|
|
|
self.nice = result['nice']
|
|
|
|
|
self.cpu = result['cpu']
|
|
|
|
|
self.time = int(result['time'])
|
|
|
|
|
else:
|
|
|
|
|
self.nice = backupUtilities.NiceDefault
|
|
|
|
|
self.cpu = backupUtilities.CPUDefault
|
|
|
|
|
self.time = int(backupUtilities.time)
|
|
|
|
|
|
|
|
|
|
self.BackupPath = self.extraArgs['path']
|
|
|
|
|
self.website = Websites.objects.get(domain=self.extraArgs['domain'])
|
|
|
|
|
|
|
|
|
|
command = 'mkdir -p %s' % (self.BackupPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Starting backup generation..,0')
|
|
|
|
|
if self.extraArgs['data']:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Generating backup for your data,5')
|
|
|
|
|
result = self.BackupData()
|
|
|
|
|
if result[0] == 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Failed to generate backups for data. Error: %s. [404], 0' % (result[1] ))
|
|
|
|
|
return 0, self.BackupPath
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Data backup successfully generated,30')
|
|
|
|
|
|
|
|
|
|
if self.extraArgs['emails']:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Generating backup for your emails,40')
|
|
|
|
|
result = self.BackupEmails()
|
|
|
|
|
if result[0] == 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Failed to generate backups for emails. Error: %s. [404], 0' % (result[1] ))
|
|
|
|
|
return 0, self.BackupPath
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Emails backup successfully generated,60')
|
|
|
|
|
|
|
|
|
|
if self.extraArgs['databases']:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Generating backup for your databases,60')
|
|
|
|
|
result = self.BackupDatabases()
|
|
|
|
|
if result[0] == 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Failed to generate backups for databases. Error: %s. [404], 0' % (result[1] ))
|
|
|
|
|
return 0, self.BackupPath
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Databases backups successfully generated,30')
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating final archive..,80')
|
|
|
|
|
|
|
|
|
|
command = 'nice -n %s tar czf %s.tar.gz -C %s %s' % (self.nice, self.BackupPath, '/home/cyberpanel/backups/%s' % (self.extraArgs['domain']), self.BackupPath.split('/')[-1])
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf %s' % (self.BackupPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
finalPath = '%s.tar.gz' % (self.BackupPath)
|
|
|
|
|
|
|
|
|
|
command = 'chown cyberpanel:cyberpanel %s' % (finalPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'chmod 600:600 %s' % (finalPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
if self.extraArgs['port'] != 0:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Sending file to destination server..,90')
|
|
|
|
|
|
|
|
|
|
command = "scp -o StrictHostKeyChecking=no -P %s -i /root/.ssh/cyberpanel %s root@%s:/home/cyberpanel/backups/%s/" % (self.extraArgs['port'], finalPath, self.extraArgs['ip'], self.extraArgs['destinationDomain'])
|
|
|
|
|
ProcessUtilities.outputExecutioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Completed [200].')
|
|
|
|
|
|
|
|
|
|
return 1, self.BackupPath + '.tar.gz'
|
|
|
|
|
|
|
|
|
|
## Restore functions
|
|
|
|
|
|
|
|
|
|
def SubmitCloudBackupRestore(self):
|
|
|
|
|
try:
|
|
|
|
|
import json
|
|
|
|
|
if os.path.exists(backupUtilities.CloudBackupConfigPath):
|
|
|
|
|
result = json.loads(open(backupUtilities.CloudBackupConfigPath, 'r').read())
|
|
|
|
|
self.nice = result['nice']
|
|
|
|
|
self.cpu = result['cpu']
|
|
|
|
|
self.time = int(result['time'])
|
|
|
|
|
else:
|
|
|
|
|
self.nice = backupUtilities.NiceDefault
|
|
|
|
|
self.cpu = backupUtilities.CPUDefault
|
|
|
|
|
self.time = int(backupUtilities.time)
|
|
|
|
|
|
|
|
|
|
self.BackupPath = '/home/cyberpanel/backups/%s/%s' % (self.extraArgs['domain'], self.extraArgs['backupFile'])
|
|
|
|
|
self.website = Websites.objects.get(domain=self.extraArgs['domain'])
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Extracting main archive..,0')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command = 'tar -xf %s -C %s' % (self.BackupPath, '/home/cyberpanel/backups/%s/' % (self.extraArgs['domain']))
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Main Archive extracted,20')
|
|
|
|
|
|
|
|
|
|
self.extractedPath = '/home/cyberpanel/backups/%s/%s' % (self.extraArgs['domain'], self.extraArgs['backupFile'].rstrip('.tar.gz'))
|
|
|
|
|
|
|
|
|
|
self.dataPath = '%s/data' % (self.extractedPath)
|
|
|
|
|
self.databasesPath = '%s/databases' % (self.extractedPath)
|
|
|
|
|
self.emailsPath = '%s/emails' % (self.extractedPath)
|
|
|
|
|
|
|
|
|
|
## Data
|
|
|
|
|
|
|
|
|
|
if os.path.exists(self.dataPath):
|
|
|
|
|
try:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating child domains if any..,20')
|
|
|
|
|
childDomains = json.loads(open('%s/data.json' % (self.extractedPath), 'r').read())['ChildDomains']
|
|
|
|
|
|
|
|
|
|
for child in childDomains:
|
|
|
|
|
try:
|
|
|
|
|
ch = ChildDomains.objects.get(domain=child['domain'])
|
|
|
|
|
except:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating %s,20' % (child['domain']))
|
|
|
|
|
virtualHostUtilities.createDomain(self.website.domain, child['domain'], child['php'], child['path'], 1, 0, 0,
|
|
|
|
|
self.website.admin.userName, 0, "/home/cyberpanel/" + str(randint(1000, 9999)))
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s [SubmitCloudBackupRestore:1533]' % str(msg))
|
|
|
|
|
|
|
|
|
|
homePath = '/home/%s' % (self.website.domain)
|
|
|
|
|
command = 'rm -rf %s' % (homePath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
if self.extraArgs['sourceDomain'] == 'None':
|
|
|
|
|
command = 'mv %s/%s %s' % (self.dataPath, self.website.domain, '/home')
|
|
|
|
|
else:
|
|
|
|
|
command = 'mv %s/%s %s/%s' % (self.dataPath, self.extraArgs['sourceDomain'], '/home', self.extraArgs['domain'])
|
|
|
|
|
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from filemanager.filemanager import FileManager
|
|
|
|
|
|
|
|
|
|
fm = FileManager(None, None)
|
|
|
|
|
fm.fixPermissions(self.website.domain)
|
|
|
|
|
|
|
|
|
|
## Emails
|
|
|
|
|
|
|
|
|
|
if os.path.exists(self.emailsPath):
|
|
|
|
|
try:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating emails if any..,40')
|
|
|
|
|
emails = json.loads(open('%s/emails.json' % (self.extractedPath), 'r').read())['emails']
|
|
|
|
|
from mailServer.models import Domains, EUsers
|
|
|
|
|
emailDomain = Domains.objects.get(domain=self.website.domain)
|
|
|
|
|
|
|
|
|
|
for email in emails:
|
|
|
|
|
try:
|
|
|
|
|
eu = EUsers.objects.get(emailOwner=emailDomain, email=email['email'])
|
|
|
|
|
except:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating %s,40' % (email['email']))
|
|
|
|
|
emailAcct = EUsers(emailOwner=emailDomain, email=email['email'], password=email['password'])
|
|
|
|
|
emailAcct.mail = 'maildir:/home/vmail/%s/%s/Maildir' % (self.website.domain, email['email'].split('@')[0])
|
|
|
|
|
emailAcct.save()
|
|
|
|
|
|
|
|
|
|
EmailsHome = '/home/vmail/%s' % (self.website.domain)
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf %s' % (EmailsHome)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'mv %s/%s /home/vmail' % (self.emailsPath, self.website.domain)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'chown -R vmail:vmail %s' % (EmailsHome)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s [SubmitCloudBackupRestore:1533]' % str(msg))
|
|
|
|
|
|
|
|
|
|
## Databases
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Restoring databases if any..,70')
|
|
|
|
|
|
|
|
|
|
databases = json.loads(open('%s/databases.json' % (self.extractedPath), 'r').read())['databases']
|
|
|
|
|
|
|
|
|
|
for db in databases:
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Restoring database %s..,70' % (db['databaseName']))
|
|
|
|
|
|
|
|
|
|
mysqlUtilities.mysqlUtilities.submitDBDeletion(db['databaseName'])
|
|
|
|
|
|
|
|
|
|
if mysqlUtilities.mysqlUtilities.createDatabase(db['databaseName'], db['databaseUser'], "cyberpanel") == 0:
|
|
|
|
|
raise BaseException("Failed to create Databases!")
|
|
|
|
|
|
|
|
|
|
newDB = Databases(website=self.website, dbName=db['databaseName'], dbUser=db['databaseUser'])
|
|
|
|
|
newDB.save()
|
|
|
|
|
|
|
|
|
|
mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(db['databaseName'], self.databasesPath, db['password'])
|
|
|
|
|
|
|
|
|
|
if self.extraArgs['sourceDomain'] != 'None':
|
|
|
|
|
if self.extraArgs['sourceDomain'] != self.extraArgs['domain']:
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
command = 'wp --info'
|
|
|
|
|
outout = ProcessUtilities.outputExecutioner(command)
|
|
|
|
|
|
|
|
|
|
if not outout.find('WP-CLI root dir:') > -1:
|
|
|
|
|
from plogical.applicationInstaller import ApplicationInstaller
|
|
|
|
|
ai = ApplicationInstaller(None, None)
|
|
|
|
|
ai.installWPCLI()
|
|
|
|
|
except subprocess.CalledProcessError:
|
|
|
|
|
from plogical.applicationInstaller import ApplicationInstaller
|
|
|
|
|
ai = ApplicationInstaller(None, None)
|
|
|
|
|
ai.installWPCLI()
|
|
|
|
|
|
|
|
|
|
path = '/home/%s/public_html' % (self.extraArgs['domain'])
|
|
|
|
|
command = "wp search-replace '%s' '%s' --path=%s --allow-root" % (self.extraArgs['sourceDomain'], self.extraArgs['domain'], path)
|
|
|
|
|
ProcessUtilities.outputExecutioner(command)
|
|
|
|
|
|
|
|
|
|
command = "wp search-replace 'www.%s' '%s' --path=%s --allow-root" % (
|
|
|
|
|
self.extraArgs['sourceDomain'], self.extraArgs['domain'], path)
|
|
|
|
|
ProcessUtilities.outputExecutioner(command)
|
|
|
|
|
|
|
|
|
|
command = "wp search-replace 'www.%s' '%s' --path=%s --allow-root" % (
|
|
|
|
|
self.extraArgs['domain'], self.extraArgs['domain'], path)
|
|
|
|
|
ProcessUtilities.outputExecutioner(command)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf %s' % (self.extractedPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Completed [200].')
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], '%s [404].' % str(msg))
|
|
|
|
|
|
|
|
|
|
### Cloud Backup functions ends
|
|
|
|
|
|
|
|
|
|
def fetchAWSKeys(self):
|
|
|
|
|
path = '/home/cyberpanel/.aws'
|
|
|
|
|
credentials = path + '/credentials'
|
|
|
|
|
|
|
|
|
|
data = open(credentials, 'r').readlines()
|
|
|
|
|
|
|
|
|
|
aws_access_key_id = data[1].split(' ')[2].strip(' ').strip('\n')
|
|
|
|
|
aws_secret_access_key = data[2].split(' ')[2].strip(' ').strip('\n')
|
|
|
|
|
region = data[3].split(' ')[2].strip(' ').strip('\n')
|
|
|
|
|
|
|
|
|
|
return aws_access_key_id, aws_secret_access_key, region
|
|
|
|
|
|
|
|
|
|
def SubmitS3BackupRestore(self):
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
import json
|
|
|
|
|
if os.path.exists(backupUtilities.CloudBackupConfigPath):
|
|
|
|
|
result = json.loads(open(backupUtilities.CloudBackupConfigPath, 'r').read())
|
|
|
|
|
self.nice = result['nice']
|
|
|
|
|
self.cpu = result['cpu']
|
|
|
|
|
self.time = int(result['time'])
|
|
|
|
|
else:
|
|
|
|
|
self.nice = backupUtilities.NiceDefault
|
|
|
|
|
self.cpu = backupUtilities.CPUDefault
|
|
|
|
|
self.time = int(backupUtilities.time)
|
|
|
|
|
|
|
|
|
|
### First Download file from S3
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Starting file download from S3..,0')
|
|
|
|
|
|
|
|
|
|
import boto3
|
|
|
|
|
from s3Backups.models import BackupPlan
|
|
|
|
|
plan = BackupPlan.objects.get(name=self.extraArgs['planName'])
|
|
|
|
|
|
|
|
|
|
aws_access_key_id, aws_secret_access_key, region = self.fetchAWSKeys()
|
|
|
|
|
|
|
|
|
|
if region.find('http') > -1:
|
|
|
|
|
s3 = boto3.resource(
|
|
|
|
|
's3',
|
|
|
|
|
aws_access_key_id=aws_access_key_id,
|
|
|
|
|
aws_secret_access_key=aws_secret_access_key,
|
|
|
|
|
endpoint_url=region
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
s3 = boto3.resource(
|
|
|
|
|
's3',
|
|
|
|
|
aws_access_key_id=aws_access_key_id,
|
|
|
|
|
aws_secret_access_key=aws_secret_access_key,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.BackupPath = '/home/cyberpanel/backups/%s/%s' % (self.extraArgs['domain'], self.extraArgs['backupFile'].split('/')[-1])
|
|
|
|
|
|
|
|
|
|
s3.Bucket(plan.bucket).download_file(self.extraArgs['backupFile'], self.BackupPath)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'File download completed..,5')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.website = Websites.objects.get(domain=self.extraArgs['domain'])
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Extracting main archive..,0')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command = 'tar -xf %s -C %s' % (self.BackupPath, '/home/cyberpanel/backups/%s/' % (self.extraArgs['domain']))
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Main Archive extracted,20')
|
|
|
|
|
|
|
|
|
|
self.extractedPath = '/home/cyberpanel/backups/%s/%s' % (self.extraArgs['domain'], self.extraArgs['backupFile'].split('/')[-1].rstrip('.tar.gz'))
|
|
|
|
|
|
|
|
|
|
self.dataPath = '%s/data' % (self.extractedPath)
|
|
|
|
|
self.databasesPath = '%s/databases' % (self.extractedPath)
|
|
|
|
|
self.emailsPath = '%s/emails' % (self.extractedPath)
|
|
|
|
|
|
|
|
|
|
## Data
|
|
|
|
|
|
|
|
|
|
if os.path.exists(self.dataPath):
|
|
|
|
|
try:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating child domains if any..,20')
|
|
|
|
|
childDomains = json.loads(open('%s/data.json' % (self.extractedPath), 'r').read())['ChildDomains']
|
|
|
|
|
|
|
|
|
|
for child in childDomains:
|
|
|
|
|
try:
|
|
|
|
|
ch = ChildDomains.objects.get(domain=child['domain'])
|
|
|
|
|
except:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating %s,20' % (child['domain']))
|
|
|
|
|
virtualHostUtilities.createDomain(self.website.domain, child['domain'], child['php'], child['path'], 1, 0, 0,
|
|
|
|
|
self.website.admin.userName, 0, "/home/cyberpanel/" + str(randint(1000, 9999)))
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s [SubmitCloudBackupRestore:1533]' % str(msg))
|
|
|
|
|
|
|
|
|
|
homePath = '/home/%s' % (self.website.domain)
|
|
|
|
|
command = 'rm -rf %s' % (homePath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'mv %s/%s %s' % (self.dataPath, self.website.domain, '/home')
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
from filemanager.filemanager import FileManager
|
|
|
|
|
|
|
|
|
|
fm = FileManager(None, None)
|
|
|
|
|
fm.fixPermissions(self.website.domain)
|
|
|
|
|
|
|
|
|
|
## Emails
|
|
|
|
|
|
|
|
|
|
if os.path.exists(self.emailsPath):
|
|
|
|
|
try:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating emails if any..,40')
|
|
|
|
|
emails = json.loads(open('%s/emails.json' % (self.extractedPath), 'r').read())['emails']
|
|
|
|
|
from mailServer.models import Domains, EUsers
|
|
|
|
|
emailDomain = Domains.objects.get(domain=self.website.domain)
|
|
|
|
|
|
|
|
|
|
for email in emails:
|
|
|
|
|
try:
|
|
|
|
|
eu = EUsers.objects.get(emailOwner=emailDomain, email=email['email'])
|
|
|
|
|
except:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Creating %s,40' % (email['email']))
|
|
|
|
|
emailAcct = EUsers(emailOwner=emailDomain, email=email['email'], password=email['password'])
|
|
|
|
|
emailAcct.mail = 'maildir:/home/vmail/%s/%s/Maildir' % (self.website.domain, email['email'].split('@')[0])
|
|
|
|
|
emailAcct.save()
|
|
|
|
|
|
|
|
|
|
EmailsHome = '/home/vmail/%s' % (self.website.domain)
|
|
|
|
|
|
|
|
|
|
command = f'rm -rf {EmailsHome}'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'mv %s/%s /home/vmail' % (self.emailsPath, self.website.domain)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = 'chown -R vmail:vmail %s' % (EmailsHome)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('%s [SubmitCloudBackupRestore:1533]' % str(msg))
|
|
|
|
|
|
|
|
|
|
## Databases
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Restoring databases if any..,70')
|
|
|
|
|
|
|
|
|
|
databases = json.loads(open('%s/databases.json' % (self.extractedPath), 'r').read())['databases']
|
|
|
|
|
|
|
|
|
|
for db in databases:
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'],
|
|
|
|
|
'Restoring database %s..,70' % (db['databaseName']))
|
|
|
|
|
|
|
|
|
|
mysqlUtilities.mysqlUtilities.submitDBDeletion(db['databaseName'])
|
|
|
|
|
|
|
|
|
|
if mysqlUtilities.mysqlUtilities.createDatabase(db['databaseName'], db['databaseUser'], "cyberpanel") == 0:
|
|
|
|
|
raise BaseException("Failed to create Databases!")
|
|
|
|
|
|
|
|
|
|
newDB = Databases(website=self.website, dbName=db['databaseName'], dbUser=db['databaseUser'])
|
|
|
|
|
newDB.save()
|
|
|
|
|
|
|
|
|
|
mysqlUtilities.mysqlUtilities.restoreDatabaseBackup(db['databaseName'], self.databasesPath, db['password'])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command = 'rm -rf %s' % (self.extractedPath)
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], 'Completed [200].')
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.statusWriter(self.extraArgs['tempStatusPath'], '%s [404].' % str(msg))
|
|
|
|
|
|
|
|
|
|
def submitBackupCreation(tempStoragePath, backupName, backupPath, backupDomain):
|
|
|
|
|
try:
|
|
|
|
|
## /home/example.com/backup/backup-example.com-02.13.2018_10-24-52 -- tempStoragePath
|
|
|
|
|
## backup-example.com-02.13.2018_10-24-52 -- backup name
|
|
|
|
|
## /home/example.com/backup - backupPath
|
|
|
|
|
## /home/cyberpanel/1047.xml - metaPath
|
|
|
|
|
## /home/backup/<random_number> - CPHomeStorage
|
|
|
|
|
|
|
|
|
|
status = os.path.join(backupPath, 'status')
|
|
|
|
|
|
|
|
|
|
### Lets first see if enough space for backups is available
|
|
|
|
|
|
|
|
|
|
from plogical.IncScheduler import IncScheduler
|
|
|
|
|
import json
|
|
|
|
|
from plogical.getSystemInformation import SystemInformation
|
|
|
|
|
#
|
|
|
|
|
# IncScheduler.CalculateAndUpdateDiskUsage()
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
website = Websites.objects.get(domain=backupDomain)
|
|
|
|
|
DiskUsageOfSite = json.loads(website.config)['DiskUsage']
|
|
|
|
|
used_disk, free_disk, percent_used = SystemInformation.GetRemainingDiskUsageInMBs()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if float(free_disk) <= float(DiskUsageOfSite):
|
|
|
|
|
command = f"echo 'Disk space exceeded the website size. [2065][5009]' > %s"
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
return 0
|
|
|
|
|
except:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
website = Websites.objects.get(domain=backupDomain)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
CPHomeStorage = f'/home/backup/{generate_pass(5)}'
|
|
|
|
|
|
|
|
|
|
### Now make this random directory to store data so taht we dont run any root file operations in user home dir
|
|
|
|
|
|
|
|
|
|
command = f'mkdir -p {CPHomeStorage} && chown {website.externalApp}:{website.externalApp} {CPHomeStorage}'
|
|
|
|
|
ProcessUtilities.executioner(command, 'root', True)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
schedulerPath = f'/home/cyberpanel/{backupDomain}-backup.txt'
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
command = f'mkdir -p {tempStoragePath}'
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
command = f'touch {status}'
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
|
|
|
|
|
result = backupUtilities.prepareBackupMeta(backupDomain, backupName, tempStoragePath, backupPath)
|
|
|
|
|
|
|
|
|
|
if result[0] == 0:
|
|
|
|
|
writeToFile = open(schedulerPath, 'w')
|
|
|
|
|
writeToFile.writelines('1325')
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
command = "echo '%s [1084][5009]' > %s" % (str(result[1]), status)
|
|
|
|
|
ProcessUtilities.executioner(command, website.externalApp)
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command = 'chown %s:%s %s' % (website.externalApp, website.externalApp, result[2])
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(backupPath)
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(tempStoragePath)
|
|
|
|
|
|
|
|
|
|
execPath = "sudo nice -n 10 /usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/backupUtilities.py"
|
|
|
|
|
execPath = execPath + " startBackup --tempStoragePath " + tempStoragePath + " --backupName " \
|
|
|
|
|
+ backupName + " --backupPath " + backupPath + ' --backupDomain ' + backupDomain + ' --metaPath %s' % (
|
|
|
|
|
result[2])
|
|
|
|
|
|
|
|
|
|
output = ProcessUtilities.outputExecutioner(execPath, website.externalApp)
|
|
|
|
|
|
|
|
|
|
if output.find('[5009]') > -1:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(output)
|
|
|
|
|
writeToFile = open(schedulerPath, 'w')
|
|
|
|
|
writeToFile.writelines(output)
|
|
|
|
|
writeToFile.close()
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
## Backing up databases
|
|
|
|
|
|
|
|
|
|
command = f'chown cyberpanel:cyberpanel {result[2]}'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
backupMetaData = ElementTree.parse(result[2])
|
|
|
|
|
|
|
|
|
|
databases = backupMetaData.findall('Databases/database')
|
|
|
|
|
|
|
|
|
|
for database in databases:
|
|
|
|
|
|
|
|
|
|
dbName = database.find('dbName').text
|
|
|
|
|
res = mysqlUtilities.mysqlUtilities.createDatabaseBackup(dbName, '/home/cyberpanel')
|
|
|
|
|
if res == 0:
|
|
|
|
|
## This login can be further improved later.
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile('Failed to create database backup for %s. This could be false positive, moving on.' % (dbName))
|
|
|
|
|
|
|
|
|
|
command = f'mv /home/cyberpanel/{dbName}.sql {CPHomeStorage}/{dbName}.sql'
|
|
|
|
|
ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##
|
|
|
|
|
|
|
|
|
|
#output = ProcessUtilities.outputExecutioner(execPath, website.externalApp)
|
|
|
|
|
|
|
|
|
|
execPath = "sudo nice -n 10 /usr/local/CyberCP/bin/python " + virtualHostUtilities.cyberPanel + "/plogical/backupUtilities.py"
|
|
|
|
|
execPath = execPath + " BackupRoot --tempStoragePath " + tempStoragePath + " --backupName " \
|
|
|
|
|
+ backupName + " --backupPath " + backupPath + ' --backupDomain ' + backupDomain + ' --metaPath %s --externalApp %s' % (
|
|
|
|
|
result[2], website.externalApp) + f' --CPHomeStorage {CPHomeStorage}'
|
|
|
|
|
|
|
|
|
|
ProcessUtilities.executioner(execPath, 'root')
|
|
|
|
|
|
|
|
|
|
#command = 'chown -R %s:%s %s' % (website.externalApp, website.externalApp, backupPath)
|
|
|
|
|
#ProcessUtilities.executioner(command)
|
|
|
|
|
|
|
|
|
|
command = f'rm -f {result[2]}'
|
|
|
|
|
ProcessUtilities.executioner(command, 'cyberpanel')
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f"{str(msg)} [submitBackupCreation]")
|
|
|
|
|
|
|
|
|
|
def cancelBackupCreation(backupCancellationDomain, fileName):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
path = f"/home/{backupCancellationDomain}/backup/pid"
|
|
|
|
|
|
|
|
|
|
pid = open(path, "r").readlines()[0]
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
os.kill(int(pid), signal.SIGKILL)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f"{str(msg)} [cancelBackupCreation]")
|
|
|
|
|
|
|
|
|
|
backupPath = f"/home/{backupCancellationDomain}/backup/"
|
|
|
|
|
|
|
|
|
|
tempStoragePath = backupPath + fileName
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
os.remove(f"{tempStoragePath}.tar.gz")
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f"{str(msg)} [cancelBackupCreation]")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
rmtree(tempStoragePath)
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(f"{str(msg)} [cancelBackupCreation]")
|
|
|
|
|
|
|
|
|
|
status = open(backupPath + 'status', "w")
|
|
|
|
|
status.write("Aborted manually. [1165][5009]")
|
|
|
|
|
status.close()
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
f"{str(msg)} [cancelBackupCreation]")
|
|
|
|
|
print(f"0, {str(msg)}")
|
|
|
|
|
|
|
|
|
|
def submitRestore(backupFile, dir):
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
|
|
p = Process(target=backupUtilities.startRestore, args=(backupFile, dir,))
|
|
|
|
|
p.start()
|
|
|
|
|
|
|
|
|
|
print("1,None")
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
logging.CyberCPLogFileWriter.writeToFile(
|
|
|
|
|
str(msg) + " [cancelBackupCreation]")
|
|
|
|
|
print(f"0, {str(msg)}")
|
|
|
|
|
|
|
|
|
|
def submitDestinationCreation(ipAddress, password, port='22', user='root'):
|
|
|
|
|
setupKeys = backupUtilities.setupSSHKeys(ipAddress, password, port, user)
|
|
|
|
|
|
|
|
|
|
if setupKeys[0] == 1:
|
|
|
|
|
backupUtilities.createBackupDir(ipAddress, port, user)
|
|
|
|
|
print("1,None")
|
|
|
|
|
else:
|
|
|
|
|
print(setupKeys[1])
|
|
|
|
|
|
|
|
|
|
def getConnectionStatus(ipAddress):
|
|
|
|
|
try:
|
|
|
|
|
checkCon = backupUtilities.checkConnection(ipAddress)
|
|
|
|
|
|
|
|
|
|
if checkCon[0] == 1:
|
|
|
|
|
print("1,None")
|
|
|
|
|
else:
|
|
|
|
|
print(checkCon[1])
|
|
|
|
|
|
|
|
|
|
except BaseException as msg:
|
|
|
|
|
print(str(msg))
|
|
|
|
|
|
|
|
|
|
def FetchOCBackupsFolders(id, owner):
|
|
|
|
|
# Load the private key
|
|
|
|
|
private_key_path = '/root/.ssh/cyberpanel'
|
|
|
|
|
keyPrivate = paramiko.RSAKey(filename=private_key_path)
|
|
|
|
|
|
|
|
|
|
from IncBackups.models import OneClickBackups
|
|
|
|
|
admin = Administrator.objects.get(userName=owner)
|
|
|
|
|
ocb = OneClickBackups.objects.get(pk=id, owner=admin)
|
|
|
|
|
|
|
|
|
|
nbd = NormalBackupDests.objects.get(name=ocb.sftpUser)
|
|
|
|
|
ip = json.loads(nbd.config)['ip']
|
|
|
|
|
|
|
|
|
|
# Connect to the remote server using the private key
|
|
|
|
|
ssh = paramiko.SSHClient()
|
|
|
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
|
ssh.connect(ip, username=ocb.sftpUser, pkey=keyPrivate)
|
|
|
|
|
|
|
|
|
|
# Command to list directories under the specified path
|
|
|
|
|
command = f"ls -d cpbackups/*/"
|
|
|
|
|
|
|
|
|
|
# Execute the command
|
|
|
|
|
stdin, stdout, stderr = ssh.exec_command(command)
|
|
|
|
|
|
|
|
|
|
# Read the results
|
|
|
|
|
directories = stdout.read().decode().splitlines()
|
|
|
|
|
|
|
|
|
|
# Print directories
|
|
|
|
|
for directory in directories:
|
|
|
|
|
print(directory)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
parser = argparse.ArgumentParser(description='CyberPanel Backup Generator')
|
|
|
|
|
parser.add_argument('function', help='Specify a function to call!')
|
|
|
|
|
parser.add_argument('--tempStoragePath', help='')
|
|
|
|
|
parser.add_argument('--backupName', help='!')
|
|
|
|
|
parser.add_argument('--backupPath', help='')
|
|
|
|
|
parser.add_argument('--backupDomain', help='')
|
|
|
|
|
parser.add_argument('--metaPath', help='')
|
|
|
|
|
|
|
|
|
|
## Destination Creation
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--ipAddress', help='')
|
|
|
|
|
parser.add_argument('--password', help='')
|
|
|
|
|
parser.add_argument('--port', help='')
|
|
|
|
|
parser.add_argument('--user', help='')
|
|
|
|
|
|
|
|
|
|
## backup cancellation arguments
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--backupCancellationDomain', help='')
|
|
|
|
|
parser.add_argument('--fileName', help='')
|
|
|
|
|
|
|
|
|
|
## backup restore arguments
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--backupFile', help='')
|
|
|
|
|
parser.add_argument('--dir', help='')
|
|
|
|
|
|
|
|
|
|
### For Cloud Backups
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--data', help='')
|
|
|
|
|
parser.add_argument('--emails', help='')
|
|
|
|
|
parser.add_argument('--databases', help='')
|
|
|
|
|
parser.add_argument('--path', help='')
|
|
|
|
|
parser.add_argument('--ip', help='')
|
|
|
|
|
parser.add_argument('--sourceDomain', help='')
|
|
|
|
|
parser.add_argument('--destinationDomain', help='')
|
|
|
|
|
|
|
|
|
|
## FOR S3
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--planName', help='')
|
|
|
|
|
parser.add_argument('--externalApp', help='')
|
|
|
|
|
|
|
|
|
|
### CPHomeStorage
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--CPHomeStorage', help='')
|
|
|
|
|
|
|
|
|
|
### id
|
|
|
|
|
|
|
|
|
|
parser.add_argument('--id', help='')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
if args.function == "submitBackupCreation":
|
|
|
|
|
submitBackupCreation(args.tempStoragePath, args.backupName, args.backupPath, args.backupDomain)
|
|
|
|
|
elif args.function == "cancelBackupCreation":
|
|
|
|
|
cancelBackupCreation(args.backupCancellationDomain, args.fileName)
|
|
|
|
|
elif args.function == "submitRestore":
|
|
|
|
|
submitRestore(args.backupFile, args.dir)
|
|
|
|
|
elif args.function == "submitDestinationCreation":
|
|
|
|
|
submitDestinationCreation(args.ipAddress, args.password, args.port, args.user)
|
|
|
|
|
elif args.function == "getConnectionStatus":
|
|
|
|
|
getConnectionStatus(args.ipAddress)
|
|
|
|
|
elif args.function == "startBackup":
|
|
|
|
|
backupUtilities.startBackup(args.tempStoragePath, args.backupName, args.backupPath, args.metaPath)
|
|
|
|
|
elif args.function == "BackupRoot":
|
|
|
|
|
backupUtilities.BackupRoot(args.tempStoragePath, args.backupName, args.backupPath, args.metaPath, args.externalApp, args.CPHomeStorage)
|
|
|
|
|
elif args.function == 'CloudBackup':
|
|
|
|
|
extraArgs = {}
|
|
|
|
|
extraArgs['domain'] = args.backupDomain
|
|
|
|
|
extraArgs['tempStatusPath'] = args.tempStoragePath
|
|
|
|
|
extraArgs['data'] = int(args.data)
|
|
|
|
|
extraArgs['emails'] = int(args.emails)
|
|
|
|
|
extraArgs['databases'] = int(args.databases)
|
|
|
|
|
extraArgs['path'] = args.path
|
|
|
|
|
extraArgs['port'] = args.port
|
|
|
|
|
extraArgs['ip'] = args.ip
|
|
|
|
|
extraArgs['destinationDomain'] = args.destinationDomain
|
|
|
|
|
bu = backupUtilities(extraArgs)
|
|
|
|
|
bu.CloudBackups()
|
|
|
|
|
|
|
|
|
|
elif args.function == 'SubmitCloudBackupRestore':
|
|
|
|
|
extraArgs = {}
|
|
|
|
|
extraArgs['domain'] = args.backupDomain
|
|
|
|
|
extraArgs['tempStatusPath'] = args.tempStoragePath
|
|
|
|
|
extraArgs['backupFile'] = args.backupFile
|
|
|
|
|
extraArgs['sourceDomain'] = args.sourceDomain
|
|
|
|
|
bu = backupUtilities(extraArgs)
|
|
|
|
|
bu.SubmitCloudBackupRestore()
|
|
|
|
|
elif args.function == 'SubmitS3BackupRestore':
|
|
|
|
|
extraArgs = {}
|
|
|
|
|
extraArgs['domain'] = args.backupDomain
|
|
|
|
|
extraArgs['tempStatusPath'] = args.tempStoragePath
|
|
|
|
|
extraArgs['backupFile'] = args.backupFile
|
|
|
|
|
extraArgs['planName'] = args.planName
|
|
|
|
|
bu = backupUtilities(extraArgs)
|
|
|
|
|
bu.SubmitS3BackupRestore()
|
|
|
|
|
|
|
|
|
|
elif args.function == 'FetchOCBackupsFolders':
|
|
|
|
|
FetchOCBackupsFolders(args.id, args.user)
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|