Python rsync to copy the logs from multiple remote servers
Review


Constants should be UPPER_SNAKE_CASE
More (and better) functions! 


Lot of this code is in the global namespace, which is bad (not maintainable)
Why is sync doing argument parsing?

You should split up your code into individual instructions

Same goes for the logic of hosts splitting, these really should be part of another function (maybe parse_arguments)

Go with new style formatting or fstrings python3.6+
Simplify the split(',') using join()
Don't do manual path appending but use os.path.join()
Top it off with a if __name__ == '__main__'


Code

#!/usr/bin/python3
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import smtplib
import subprocess
import argparse
import os

DEST_DIR = "/infralogs/external_dns_logs"
RSYNC_USER = "root"

EMAIL_SENDER = "dnslogger@udalt.com"
EMAIL_RECIEVER = "gusain@udalt.com"
EMAIL_CC = "gusain@udalt.com"

def parse_arguments():
    parser = argparse.ArgumentParser()
    parser.add_argument("-n","--hosts", dest="hosts", help="enter remote host/hosts name, comma seperated", metavar="HOSTS")
    parser.add_argument("-s","--src", dest="source", help="source file/directory", metavar="SOURCE")
    parser.add_argument("-e","--exclude", dest="exclude", help="Exclude files/Directories, comma seperated list", metavar="EXCLUDE")
    args = parser.parse_args()

    if args.exclude is None or args.source is None or args.hosts is None:
        parser.print_help()
        parser.exit()

    args.exclude = " --exclude " + " --exclude".join(args.exclude.split(','))
    args.hosts = args.hosts.split(',')
    return args.hosts, args.source, args.exclude

def sync(hosts, src, exclude):
    for host in hosts:
        host = host.strip()
        dest = os.path.join(DEST_DIR, host)
        cmd = f"rsync -e 'ssh -o StrictHostKeyChecking=no' -auPz {exclude} {RSYNC_USER}@{host}:{src} {dest}/"
        p = subprocess.Popen(cmd, shell=True)
        p.wait()
        yield f"{cmd} Rsync process completed."

def mail(message):
    try:
        Mail = smtplib.SMTP('mailserver.global.udalt.com', 25, 'localhost.udalt.com')
        mail_obj = MIMEMultipart('alternative')
        mail_obj["From"] = EMAIL_SENDER
        mail_obj["To"] = EMAIL_RECIEVER
        mail_obj["Cc"] = EMAIL_CC
        mail_obj["Subject"] = "Rsync process completed Successfully."
        mail_obj.attach(MIMEText(msg, 'plain'))
        Mail.sendmail(from_addr=[EMAIL_SENDER], to_addrs=[EMAIL_RECIEVER],msg=mail_obj.as_string())
        print(f"Mail Sent to {EMAIL_SENDER}")
        print(message)
    except Exception as error:
        print(f"Mail Failed - {error}")

if __name__ == '__main__':
    if not os.path.exists(DEST_DIR):
        os.mkdir(DEST_DIR)

    for msg in sync(*parse_arguments()):
        mail(msg)