125 lines
5.2 KiB
Python
Executable File
125 lines
5.2 KiB
Python
Executable File
from datetime import timedelta
|
|
|
|
import requests
|
|
from odoo import models, fields, api, _
|
|
import logging
|
|
import os
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class SaaSApp(models.Model):
|
|
_inherit = 'kk_odoo_saas.app'
|
|
backup_db_name = fields.Char(string="Database Name", default=lambda a: a.client_db_name)
|
|
backup_master_pass = fields.Char(string="Master Password")
|
|
backups_enabled = fields.Boolean()
|
|
|
|
backups = fields.Many2many(comodel_name='kk_odoo_saas.app.backup', string='Backups')
|
|
|
|
def action_create_backup(self):
|
|
"""
|
|
It is being called from 2 locations
|
|
:return:
|
|
"""
|
|
for app in self:
|
|
response = self.backup_db()
|
|
backup = self.env['kk_odoo_saas.app.backup'].create({'backup_date_time': fields.Datetime.now(),
|
|
'app': app.id,
|
|
'file_name': response.get('filename'),
|
|
'file_path': response.get('filepath'),
|
|
'message': response.get('message')
|
|
})
|
|
if response.get('success'):
|
|
backup.write({'status': 'success'})
|
|
else:
|
|
backup.write({'status': 'failed'})
|
|
app.write({'backups': [(4, backup.id)]})
|
|
|
|
def action_delete_old_backup(self):
|
|
for app in self:
|
|
for backup in app.backups:
|
|
if backup.backup_date_time < fields.Datetime.now() - timedelta(days=7.0):
|
|
if os.path.exists(backup.file_path):
|
|
try:
|
|
os.remove(backup.file_path)
|
|
if backup.url:
|
|
# deleting the attachments related to this backup
|
|
att_id = backup.url.replace('?download=true', '').replace('/web/content/', '')
|
|
if att_id:
|
|
try:
|
|
attch_id = int(att_id)
|
|
if attch_id:
|
|
self.env['ir.attachment'].browse([attch_id]).unlink()
|
|
except ValueError as e:
|
|
_logger.error(e)
|
|
backup.unlink()
|
|
except OSError as e:
|
|
_logger.error("Error while deleting file: %s - %s." % (e.filename, e.strerror))
|
|
else:
|
|
_logger.error("The file does not exist")
|
|
|
|
def backup_db(self):
|
|
"""
|
|
Actual Backup function
|
|
:return:
|
|
"""
|
|
# get the creds for db manager
|
|
data = {
|
|
'master_pwd': self.backup_master_pass,
|
|
'name': self.backup_db_name,
|
|
'backup_format': 'zip'
|
|
}
|
|
|
|
client_url = 'https://{0}{1}'.format(self.sub_domain_name, self.domain_name)
|
|
msg = ''
|
|
|
|
# where we want to store backups, in the linux user, with which the odoo-service is running
|
|
backup_dir = os.path.join(os.path.expanduser('~'), 'client_backups')
|
|
if not os.path.exists(backup_dir):
|
|
os.mkdir(backup_dir)
|
|
|
|
backup_dir = os.path.join(backup_dir, self.sub_domain_name)
|
|
if not os.path.exists(backup_dir):
|
|
os.mkdir(backup_dir)
|
|
|
|
client_url += '/web/database/backup'
|
|
# Without Streaming method
|
|
# response = requests.post(client_url, data=data)
|
|
# Streaming zip, so that everything is not stored in RAM.
|
|
|
|
try:
|
|
filename = self.backup_db_name + '-' + fields.Datetime.now().strftime("%m-%d-%Y-%H-%M") + '.zip'
|
|
backed_up_file_path = os.path.join(backup_dir, filename)
|
|
with requests.post(client_url, data=data, stream=True) as response:
|
|
response.raise_for_status()
|
|
with open(os.path.join(backup_dir, filename), 'wb') as file:
|
|
for chunk in response.iter_content(chunk_size=1024):
|
|
if chunk:
|
|
file.write(chunk)
|
|
msg = 'Database backup Successful at ' + fields.Datetime.now().strftime("%m-%d-%Y-%H:%M:%S")
|
|
return {
|
|
'success': True,
|
|
'msg': msg,
|
|
'filename': filename,
|
|
'filepath': backed_up_file_path
|
|
}
|
|
except Exception as e:
|
|
msg = 'Failed at ' + fields.Datetime.now().strftime("%m-%d-%Y-%H:%M:%S") + ' ' + str(e)
|
|
return {
|
|
'success': False,
|
|
'msg': msg
|
|
}
|
|
|
|
@api.model
|
|
def ignite_backup_server_cron(self):
|
|
"""
|
|
A Scheduled Action which will take new backups and del old
|
|
:return: False
|
|
"""
|
|
# search for saas instance in lanched and modified states and backups enabled
|
|
apps = self.env['kk_odoo_saas.app'].sudo().search(
|
|
[('status', 'in', ['l', 'm']), ('backups_enabled', '=', True)])
|
|
|
|
for app in apps:
|
|
app.action_create_backup()
|
|
app.action_delete_old_backup()
|