@@ -135,7 +135,9 @@ def getAWSData(self):
135135 secret = open (path , 'r' ).read ()
136136 return key , secret
137137
138- def awsFunction (self , fType , backupPath = None , snapshotID = None , bType = None ):
138+ ## Last argument delete is set when the snapshot is to be deleted from this repo, when this argument is set, any preceding argument is not used
139+
140+ def awsFunction (self , fType , backupPath = None , snapshotID = None , bType = None , delete = None ):
139141 try :
140142 if fType == 'backup' :
141143 key , secret = self .getAWSData ()
@@ -184,6 +186,25 @@ def awsFunction(self, fType, backupPath=None, snapshotID=None, bType=None):
184186 if result .find ('restoring' ) == - 1 :
185187 logging .statusWriter (self .statusPath , 'Failed: %s. [5009]' % (result ), 1 )
186188 return 0
189+ elif delete :
190+
191+ self .backupDestinations = self .jobid .destination
192+
193+ key , secret = self .getAWSData ()
194+
195+ command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s forget %s --password-file %s' % (
196+ key , secret , self .website , snapshotID , self .passwordFile )
197+
198+ result = ProcessUtilities .outputExecutioner (command )
199+
200+ if result .find ('removed snapshot' ) == - 1 :
201+ logging .statusWriter (self .statusPath , 'Failed: %s. [5009]' % (result ), 1 )
202+ return 0
203+
204+ command = 'export AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s && restic -r s3:s3.amazonaws.com/%s prune --password-file %s' % (
205+ key , secret , self .website , self .passwordFile )
206+
207+ ProcessUtilities .outputExecutioner (command )
187208 else :
188209 self .backupDestinations = self .jobid .destination
189210
@@ -205,7 +226,10 @@ def awsFunction(self, fType, backupPath=None, snapshotID=None, bType=None):
205226 logging .statusWriter (self .statusPath , "%s [88][5009]" % (str (msg )), 1 )
206227 return 0
207228
208- def localFunction (self , backupPath , type , restore = None ):
229+ ## Last argument delete is set when the snapshot is to be deleted from this repo, when this argument is set, any preceding argument is not used
230+
231+ def localFunction (self , backupPath , type , restore = None , delete = None ):
232+
209233 if restore == None :
210234 # Define our excludes file for use with restic
211235 backupExcludesFile = '/home/%s/backup-exclude.conf' % (self .website .domain )
@@ -233,6 +257,21 @@ def localFunction(self, backupPath, type, restore=None):
233257 newSnapshot = JobSnapshots (job = self .jobid , type = '%s:%s' % (type , backupPath ), snapshotid = snapShotid ,
234258 destination = self .backupDestinations )
235259 newSnapshot .save ()
260+ return 1
261+ elif delete :
262+
263+ repoLocation = '/home/%s/incbackup' % (self .website )
264+
265+ command = 'restic -r %s forget %s --password-file %s' % (repoLocation , self .jobid .snapshotid , self .passwordFile )
266+ result = ProcessUtilities .outputExecutioner (command )
267+
268+ if result .find ('removed snapshot' ) == - 1 :
269+ logging .statusWriter (self .statusPath , 'Failed: %s. [5009]' % (result ), 1 )
270+ return 0
271+
272+ command = 'restic -r %s prune --password-file %s' % (repoLocation , self .passwordFile )
273+ ProcessUtilities .outputExecutioner (command )
274+
236275 return 1
237276 else :
238277 repoLocation = '/home/%s/incbackup' % (self .website )
@@ -247,7 +286,9 @@ def localFunction(self, backupPath, type, restore=None):
247286
248287 return 1
249288
250- def sftpFunction (self , backupPath , type , restore = None ):
289+ ## Last argument delete is set when the snapshot is to be deleted from this repo, when this argument is set, any preceding argument is not used
290+
291+ def sftpFunction (self , backupPath , type , restore = None , delete = None ):
251292 if restore == None :
252293 # Define our excludes file for use with restic
253294 backupExcludesFile = '/home/%s/backup-exclude.conf' % (self .website .domain )
@@ -276,6 +317,17 @@ def sftpFunction(self, backupPath, type, restore=None):
276317 destination = self .backupDestinations )
277318 newSnapshot .save ()
278319 return 1
320+ elif delete :
321+ repoLocation = '/home/backup/%s' % (self .website )
322+ command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s forget %s --password-file %s' % (
323+ self .jobid .destination , repoLocation , self .jobid .snapshotid , self .passwordFile )
324+ result = ProcessUtilities .outputExecutioner (command )
325+ if result .find ('removed snapshot' ) == - 1 :
326+ logging .statusWriter (self .statusPath , 'Failed: %s. [5009]' % (result ), 1 )
327+ return 0
328+
329+ command = 'export PATH=${PATH}:/usr/bin && restic -r %s:%s prune --password-file %s' % (self .jobid .destination , repoLocation , self .passwordFile )
330+ ProcessUtilities .outputExecutioner (command )
279331 else :
280332 if self .reconstruct == 'remote' :
281333 repoLocation = '/home/backup/%s' % (self .website )
@@ -437,6 +489,7 @@ def reconstructWithMeta(self):
437489
438490 def restorePoint (self ):
439491 try :
492+
440493 self .statusPath = self .extraArgs ['tempPath' ]
441494 self .website = self .extraArgs ['website' ]
442495 jobid = self .extraArgs ['jobid' ]
@@ -526,177 +579,29 @@ def restorePoint(self):
526579 def prepareBackupMeta (self ):
527580 try :
528581
529- ######### Generating meta
530-
531- ## XML Generation
532-
533- metaFileXML = Element ('metaFile' )
534-
535- child = SubElement (metaFileXML , 'masterDomain' )
536- child .text = self .website .domain
537-
538- child = SubElement (metaFileXML , 'phpSelection' )
539- child .text = self .website .phpSelection
540-
541- child = SubElement (metaFileXML , 'externalApp' )
542- child .text = self .website .externalApp
543-
544- childDomains = self .website .childdomains_set .all ()
545-
546- databases = self .website .databases_set .all ()
547-
548- ## Child domains XML
549-
550- childDomainsXML = Element ('ChildDomains' )
551-
552- for items in childDomains :
553- childDomainXML = Element ('domain' )
554-
555- child = SubElement (childDomainXML , 'domain' )
556- child .text = items .domain
557- child = SubElement (childDomainXML , 'phpSelection' )
558- child .text = items .phpSelection
559- child = SubElement (childDomainXML , 'path' )
560- child .text = items .path
561-
562- childDomainsXML .append (childDomainXML )
563-
564- metaFileXML .append (childDomainsXML )
565-
566- ## Databases XML
567-
568- databasesXML = Element ('Databases' )
569-
570- for items in databases :
571- try :
572- dbuser = DBUsers .objects .get (user = items .dbUser )
573- userToTry = items .dbUser
574- except :
575- dbusers = DBUsers .objects .all ().filter (user = items .dbUser )
576- for it in dbusers :
577- dbuser = it
578- break
579-
580- userToTry = mysqlUtilities .mysqlUtilities .fetchuser (items .dbName )
581-
582- if userToTry == 0 or userToTry == 1 :
583- continue
584-
585- try :
586- dbuser = DBUsers .objects .get (user = userToTry )
587- except :
588- dbusers = DBUsers .objects .all ().filter (user = userToTry )
589- for it in dbusers :
590- dbuser = it
591- break
592-
593-
594- databaseXML = Element ('database' )
595-
596- child = SubElement (databaseXML , 'dbName' )
597- child .text = items .dbName
598- child = SubElement (databaseXML , 'dbUser' )
599- child .text = userToTry
600- child = SubElement (databaseXML , 'password' )
601- child .text = dbuser .password
602-
603- databasesXML .append (databaseXML )
604-
605- metaFileXML .append (databasesXML )
606-
607- ## Get Aliases
608-
609- aliasesXML = Element ('Aliases' )
610-
611- aliases = backupUtilities .getAliases (self .website .domain )
582+ ## Use the meta function from backup utils for future improvements.
612583
613- for items in aliases :
614- child = SubElement (aliasesXML , 'alias' )
615- child .text = items
616584
617- metaFileXML .append (aliasesXML )
585+ if os .path .exists (ProcessUtilities .debugPath ):
586+ logging .writeToFile ('Creating meta for %s. [IncBackupsControl.py]' % (self .website .domain ))
618587
619- ## Finish Alias
620-
621- ## DNS Records XML
622-
623- try :
624-
625- dnsRecordsXML = Element ("dnsrecords" )
626- dnsRecords = DNS .getDNSRecords (self .website .domain )
627-
628- for items in dnsRecords :
629- dnsRecordXML = Element ('dnsrecord' )
630-
631- child = SubElement (dnsRecordXML , 'type' )
632- child .text = items .type
633- child = SubElement (dnsRecordXML , 'name' )
634- child .text = items .name
635- child = SubElement (dnsRecordXML , 'content' )
636- child .text = items .content
637- child = SubElement (dnsRecordXML , 'priority' )
638- child .text = str (items .prio )
639-
640- dnsRecordsXML .append (dnsRecordXML )
641-
642- metaFileXML .append (dnsRecordsXML )
643-
644- except BaseException as msg :
645- logging .statusWriter (self .statusPath , '%s. [158:prepMeta]' % (str (msg )), 1 )
646-
647- ## Email accounts XML
648-
649- try :
650- emailRecordsXML = Element ('emails' )
651- eDomain = eDomains .objects .get (domain = self .website .domain )
652- emailAccounts = eDomain .eusers_set .all ()
653-
654- for items in emailAccounts :
655- emailRecordXML = Element ('emailAccount' )
656-
657- child = SubElement (emailRecordXML , 'email' )
658- child .text = items .email
659- child = SubElement (emailRecordXML , 'password' )
660- child .text = items .password
661-
662- emailRecordsXML .append (emailRecordXML )
663-
664- metaFileXML .append (emailRecordsXML )
665- except BaseException as msg :
666- pass
667- #logging.statusWriter(self.statusPath, '%s. [warning:179:prepMeta]' % (str(msg)), 1)
668-
669- ## Email meta generated!
670-
671- def prettify (elem ):
672- """Return a pretty-printed XML string for the Element.
673- """
674- rough_string = ElementTree .tostring (elem , 'utf-8' )
675- reparsed = minidom .parseString (rough_string )
676- return reparsed .toprettyxml (indent = " " )
677-
678- ## /home/example.com/backup/backup-example-06-50-03-Thu-Feb-2018/meta.xml -- metaPath
679-
680- metaPath = '/home/cyberpanel/%s' % (str (randint (1000 , 9999 )))
681-
682- xmlpretty = prettify (metaFileXML ).encode ('ascii' , 'ignore' )
683- metaFile = open (metaPath , 'w' )
684- metaFile .write (xmlpretty .decode ('utf-8' ))
685- metaFile .close ()
686- os .chmod (metaPath , 0o640 )
588+ from plogical .backupUtilities import backupUtilities
589+ status , message , metaPath = backupUtilities .prepareBackupMeta (self .website .domain , None , None , None , 0 )
687590
688591 ## meta generated
689592
690- logging .statusWriter (self .statusPath , 'Meta data is ready..' , 1 )
691-
692- metaPathNew = '/home/%s/meta.xml' % (self .website .domain )
693- command = 'mv %s %s' % (metaPath , metaPathNew )
694- ProcessUtilities .executioner (command )
695-
696- return 1
593+ if status == 1 :
594+ logging .statusWriter (self .statusPath , 'Meta data is ready..' , 1 )
595+ metaPathNew = '/home/%s/meta.xml' % (self .website .domain )
596+ command = 'mv %s %s' % (metaPath , metaPathNew )
597+ ProcessUtilities .executioner (command )
598+ return 1
599+ else :
600+ logging .statusWriter (self .statusPath , "%s [544][5009]" % (message ), 1 )
601+ return 0
697602
698603 except BaseException as msg :
699- logging .statusWriter (self .statusPath , "%s [207 ][5009]" % (str (msg )), 1 )
604+ logging .statusWriter (self .statusPath , "%s [548 ][5009]" % (str (msg )), 1 )
700605 return 0
701606
702607 def backupData (self ):
@@ -728,6 +633,7 @@ def backupDatabases(self):
728633 databases = self .website .databases_set .all ()
729634
730635 for items in databases :
636+
731637 if mysqlUtilities .mysqlUtilities .createDatabaseBackup (items .dbName , '/home/cyberpanel' ) == 0 :
732638 return 0
733639
@@ -760,6 +666,7 @@ def emailBackup(self):
760666 backupPath = '/home/vmail/%s' % (self .website .domain )
761667
762668 if os .path .exists (backupPath ):
669+
763670 if self .backupDestinations == 'local' :
764671 if self .localFunction (backupPath , 'email' ) == 0 :
765672 return 0
@@ -929,6 +836,8 @@ def createBackup(self):
929836 if self .initiateRepo () == 0 :
930837 return 0
931838
839+
840+
932841 if self .prepareBackupMeta () == 0 :
933842 return 0
934843
@@ -958,3 +867,41 @@ def createBackup(self):
958867 'Failed to delete meta file: %s. [IncJobs.createBackup.591]' % str (msg ), 1 )
959868
960869 logging .statusWriter (self .statusPath , 'Completed' , 1 )
870+
871+ ### Delete Snapshot
872+
873+ def DeleteSnapShot (self , inc_job ):
874+ try :
875+
876+ self .statusPath = logging .fileName
877+
878+ job_snapshots = inc_job .jobsnapshots_set .all ()
879+
880+ ### Fetch the website name from JobSnapshot object and set these variable as they are needed in called functions below
881+
882+ self .website = job_snapshots [0 ].job .website .domain
883+ self .passwordFile = '/home/%s/%s' % (self .website , self .website )
884+
885+ for job_snapshot in job_snapshots :
886+
887+ ## Functions above use the self.jobid varilable to extract information about this snapshot, so this below variable needs to be set
888+
889+ self .jobid = job_snapshot
890+
891+ if self .jobid .destination == 'local' :
892+ if self .localFunction ('none' , 'none' , 0 , 1 ) == 0 :
893+ return 0
894+ elif self .jobid .destination [:4 ] == 'sftp' :
895+ if self .sftpFunction ('none' , 'none' , 0 , 1 ) == 0 :
896+ return 0
897+ else :
898+ if self .awsFunction ('restore' , '' , self .jobid .snapshotid , None , 1 ) == 0 :
899+ return 0
900+
901+ return 1
902+
903+ except BaseException as msg :
904+ logging .statusWriter (self .statusPath , "%s [903:DeleteSnapShot][5009]" % (str (msg )), 1 )
905+ return 0
906+
907+
0 commit comments