def __warnIfLowSpace__(): ''' Called from checkRepositories(). Checks if disk space below notification-size. ''' pattern = re.compile(r'(\d+[M|G|T])') space = list(pattern.finditer(__getFreeDiskSpace__()))[0].group( 1 ) # get available disk-space to plain '(\d+[M|G|T])'-str (default return shape= 'X out of Y left on .') minSpace = config['notify']['warnIfDiskSpaceSmallerThan'] pattern = re.compile(r'\d+[M|G|T]') if not pattern.finditer(minSpace): return __log__( 'Invalid value for \'Warn if disk space smaller than\'-option.') # convert units if necessary # split into values- and units-part for easier processing values = [float(item[:-1]) for item in [space, minSpace]] units = [item[-1] for item in [space, minSpace]] # if unequal convert if units[0] != units[1]: order = ['M', 'G', 'T'] exp = order.index(units[0]) - order.index(units[1]) values[0] = values[0] * (1000**exp) # if available space below 'warnIfSpaceSmallerThan'-value, send warning log and mail if enabled if values[0] - values[1] < 0: return __log__( 'WARNING: Available disk space is below \'warnIfSpaceSmallerThan\'-value.\nMail-notification returned with: \'{}\'.' .format(mailingNotification().manageMailing()))
def checkRepositories(): ''' check if repos are healthty and update db-information ''' # correct format of backupPath os.path.join(config['general']['backupPath'], '') # build path to repos based on given passwords repos = [ os.path.join(config['general']['backupPath'], directory) for directory in os.listdir(os.path.join(gitProjectDir, 'passwords')) ] # check if each corresponding repo is valid status = [ 'no error' in __shell__('restic -r {} --password-file {} --no-cache check'.format( repo, os.path.join(gitProjectDir, 'passwords', repo.split('/')[-1]))) for repo in repos ] # update repository data in db for j, repo in enumerate(repos): statusNum = [1 if stat else 0 for stat in [status[j]]][0] repoSpace = __shell__('du -sh {}'.format(repo)).split('\t')[0] try: repositories.objects.update_or_create( name=repo.split('/')[-1], absolPath=repo, diskSpace=repoSpace, lastUpdate=now( ), #--> doing that initially (defined in index/models.py) health=statusNum) except: col = repositories.objects.get(absolPath=repo) col.name = repo.split('/')[-1] col.diskSpace = repoSpace col.lastUpdate = now( ) #--> doing that initially (defined in index/models.py) col.health = statusNum col.save() # execute shell "command after"-option __shell__(config['check']['executeCommandAfterCheck']) # call diskSpace-warning if necessary __warnIfLowSpace__() # if enabled, send notification # ------------------------------- result = '' if __optionIsEnabled__(config['notify']['sendMailNotifications']): result = mailingNotification().manageMailing() # if result returned something, an error occurred if result: __log__(result) return render(request, 'checkOutput.html', {'output': result})
def __getOverallSpace__(output, root): ''' Return overall and available space of disk at mountpoint ''' pattern = re.compile( r'\s+(\d+\.?\d+[A-Z]).+\s+(\d+\.?\d+[A-Z])\s+\d+%\s+{}?[\n]?$'.format( root)) for line in output.split('\n'): result = [(match.group(1), match.group(2)) for match in pattern.finditer(line)] if result: return result[0] return (__log__( 'Fatal error in __getOverallSpace__: couldn\'t determine available and overall space via regex.' ), '')
def doIntegrationAndSavePW(self): ''' This function executes the previously rendered ansible-backend and returns the exit message. ''' result = __shell__( 'ansible-playbook ./integrate/ansible_rendered/setup.yml -e \"ansible_user={0}\" -e \"ansible_ssh_pass={1}\" -e \"ansible_become_pass={1}\"' .format(self.user, self.pw)) passwdpath = os.path.join(gitProjectDir, 'passwords', ''.join(self.repoPath.split('/')[-1])) with open(passwdpath, 'w') as pwfile: pwfile.write(self.resticPW) if 'error' in result or 'Failed' in result or 'fatal' in result: __shell__('rm {}'.format(passwdpath)) return __log__( 'Error occurred while trying to integrate: {}'.format(result)) return result
def __renderAndSendMail__(self): ''' This method gets called by manageMailing(). It authenticates the user at localhost or remote-end and tries to send the previously rendered mail. Returns nothing except an error occurred. ''' # //// include these options user = self.config['smtpUsername'] password = self.config['smtpPassword'] # //// include these options content = """From: {} To: {} Subject: Castic: backup information\n This is a generic mail from your castic server. I am checking all made backups on certain time periods.\nAvailable disk-space on your backup volume: {}.\n\n""".format( self.config['mailFrom'], self.config['mailAddress'], __getFreeDiskSpace__()) # check if all repos are healthy (fetch data from db). if not, append error message errors = [ '{0} - FATAL ERROR: Error was detected in repository \'{1}\'.\nYou should check the repo and verify that the backup is done correctly.' .format(now(), list(repositories.objects.values())[j]) for j, health in enumerate( repositories.objects.values_list('health')) if health[0] != 1 ] content += '\n'.join(errors) if not errors: content += 'All integrated servers were backuped successfully.\nEverything seems clean and healthy.\n\n' content += '\nRegards,\nyour backup-friend castic.' try: smtp = smtplib.SMTP(self.config['smtpServer']) if self.config['smtpUser'] and self.config['smtpPassword']: smtp.login(self.config['smtpUser'], self.config['smtpPassword']) smtp.sendmail(self.config['mailFrom'], self.config['mailAddress'].split(','), content) except Exception as err: return __log__( ' <--SMTP--> ERROR OCCURED WHILE TRYING TO SEND MAIL: {}\n'. format(err))
def __getMountPoint__(output, root): ''' Return mountpoint of backup-disk ''' # iterate through possible mount-points by cutting /<something> after each iterat. mountPoint = [] while not mountPoint: # update root by cutting last /<something> root = '/'.join(root.split('/')[:-1]) if not root: root = '/' # check if mountpoint exists for line in output.split('\n'): pattern = re.compile(r'({}/?)$'.format(root)) mountPoint = [match.group(1) for match in pattern.finditer(line)] if mountPoint: if len(mountPoint) != 1: return __log__( 'Fatal error in index/views __getFreeDiskSpace__(): len of matched disk-mounts != 1.' ) return mountPoint[0]