How to create scheduled reports in SynetoOS 4

Written By Christian Castagna (Administrator)

Updated at April 11th, 2025

→ Applies to: SynetoOS 4.x

 

Step 1. Connect to SynetoOS appliance via SSH as admin

ssh admin@<your_ip_address_or_hostname>

 

Step 2. Remove User Shell 

rm /var/storage/admin/.bash_profile

 

Step 3. Create file report-protections.py

vim /tmp/report-protections.py

 

Step 4. Add this script to the file just created at step 3 (replace <email_server>, <email_port>, <email_username>, <email_password>, <email_send_from>, <email_send_to_1>, <email_send_to_2> with the correct information)

#!/usr/bin/env python3
import json
from collections import defaultdict
from subprocess import Popen, PIPE
from csv import DictWriter, QUOTE_MINIMAL
from datetime import datetime
import smtplib
from pathlib import Path
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from email import encoders

# can be True or False
send_email = False 

email_server = "<email_server>"
email_port = <email_port>
email_username = "<email_username>"
email_password = "<email_password>"
email_send_from = "<email_send_from>"
# this should always be a list of email addresses in quotes, comma separated:
email_send_to = ['<email_send_to_1>','<email_send_to_2>']



def _run(cmd):
    result = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=True)
    stdout, stderr = result.communicate()
    if len(stderr.decode()) != 0:
        print('{0} failed with {1}'.format(cmd, stderr))
        sys.exit(0)
    else:
        return stdout.decode()


def recursive_dict():
    return defaultdict(recursive_dict)


def generate_report():
    day = {
        '1': 'MON',
        '2': 'TUE',
        '3': 'WED',
        '4': 'THU',
        '5': 'FRI',
        '6': 'SAT',
        '0': 'SUN'
    }

    today = datetime.strftime(datetime.now(), '%Y/%m/%d')
    cmd = 'invoke-lego-api Backup\\\\Facade getSnapshotServicesAsHash -J'
    data = json.loads(_run(cmd))
    result = recursive_dict()
    for k, v in data.items():
        for policy, details in v.items():
            try:
                del result[k]['at']
            except KeyError:
                pass
            
            if details['enabled']:
                result[k][policy]['Active'] = 'Yes'
            else:
                result[k][policy]['Active'] = 'No'
            result[k][policy]['Frequency'] = details['schedule']['interval']
            step = details['schedule']['step']
            if details['schedule']['interval'] == 'weeks':
                if len(details['schedule']['weekDays']) > 1:
                    days = [day[i] for i in details['schedule']['weekDays'].split(',')]
                else:
                    days = day[details['schedule']['weekDays']]
                at = "{}:{}".format(details['schedule']['hour'], details['schedule']['minute'])
                result[k][policy]['Schedule'] = 'Every {} at {}'.format(days, at)
            elif details['schedule']['interval'] == 'days':
                at = "{}:{}".format(details['schedule']['hour'], details['schedule']['minute'])
                result[k][policy]['Schedule'] = 'Every {} {} at {}'.format(step, policy, at)
            elif details['schedule']['interval'] == 'minute':
                at = details['schedule']['minute']
                result[k][policy]['Schedule'] = 'Every {} {} at minute {}'.format(step, policy, at)
            else:
                result[k][policy]['Schedule'] = 'Every {} {}'.format(step, policy)
            
            result[k][policy]['Retention'] = "Keep {} locally".format(details['schedule']['retentionPolicy'])
            
            if len(details['replication']) != 0:
                result[k][policy]['replication_host'] = details['replication']['host']
                result[k][policy]['Replication Retention'] = "Keep {} remotely".format(details['replication']['retentionPolicy'])
            else:
                result[k][policy]['replication_host'] = ''
                result[k][policy]['Replication Retention'] = ''


    columns = ['PATH', 'Active', 'Frequency', 'Schedule', 'Retention', 'Replication Host', 'Replication Retention']
    content = open(filename, 'w')
    writer = DictWriter(content, fieldnames=columns, delimiter=',', quoting=QUOTE_MINIMAL)
    writer.writeheader()
    
    for k, v in result.items():
        for policy, values in v.items():
            row = defaultdict(dict)
            row['PATH'] = k.split('/')[-1:][0]
            row['Active'] = values['Active']
            row['Frequency'] = values['Frequency']
            row['Schedule'] = values['Schedule']
            row['Retention'] = values['Retention']
            row['Replication Host'] = values['replication_host']
            row['Replication Retention'] = values['Replication Retention']
            writer.writerow(row)

    content.close()

    with open(filename, 'r') as f:
        lines = f.readlines()

    with open(filename, 'w') as f:
        f.write('Serial: {}\n'.format(serial))
        f.write('Date: {}\n'.format(today))
        f.write('Protections Scheduling Report\n')
        f.writelines(lines)


def send_mail(use_tls=True):

    server = <email_server>
    port = <email_port>
    username = <email_username>
    password = <email_password>
    send_to = <email_send_to>
    send_from = <email_send_from>
    subject = 'Protections Scheduling Report - {}'.format(serial)
    message = "Protections Schendule Report on machine {}\n".format(serial)

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach(MIMEText(message))

    part = MIMEBase('application', "octet-stream")
    with open(filename, 'rb') as file:
        part.set_payload(file.read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', 'attachment; filename={}'.format(filename))
    msg.attach(part)
    smtp = smtplib.SMTP(server, port)
    if use_tls:
        smtp.starttls()
    smtp.login(username, password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.quit()


if __name__ == '__main__':
    serial = _run('smbios -t 1|grep Serial').split(':')[1].strip()
    filename = '{}_protections.csv'.format(serial)
    generate_report()
    if send_email:
        send_mail()

 

Step 5. Give execution permissions to the file report-protections.py

chmod +x /tmp/report-protections.py

 

Step 6. Run the script 

./tmp/report-protections.py

 

Step 7. The script creates a CSV file as output, that you can export.