#!/usr/bin/python from datetime import date,datetime import os, errno, sqlite3, sys, getopt, shutil database = "domains.db" homedir = "/var/www" def main(argv): """domainctl is a tool for managing domains, subdomains, users, and email addresses.""" if argv == []: usage() try: opts, args = getopt.getopt(argv, "acd:DeEghiluvz", ["add", "create", "delete=", "dir", "domainemail", "useremail", "ip", "generate", "help", "list", "user", "vhost", "zone"]) except getopt.GetoptError: usage() for opt, arg in opts: if opt in ("-a", "--add"): if len(args) < 3: usage() subdomain, domain = split_args(args[0]) user = args[1] email = args[2] ip = args[3] add_domain(subdomain, domain, user, email, ip) elif opt in ("-c", "--create"): create_db() elif opt in ("-d", "--delete"): if len(args) < 1: usage() if arg in ("u", "user"): delete_user(args[0]) elif arg in ("d", "domain"): subdomain, domain = split_args(args[0]) if subdomain: delete_subdomain(subdomain, domain) else: delete_domain(domain) else: usage() elif opt in ("-D", "--dir"): if len(args) < 1: usage() subdomain, domain = split_args(args[0]) build_structure(subdomain, domain) elif opt in ("-e", "--domainemail"): if len(args) < 2: usage() subdomain, domain = split_args(args[0]) email = args[1] set_domain_email(subdomain, domain, email) elif opt in ("-E", "--useremail"): if len(args) < 2: usage() user = args[0] email = args[1] set_user_email(user, email) elif opt in ("-g", "--generate"): if len(args) < 1: usage() subdomain, domain = split_args(args[0]) build_vhost(subdomain, domain) build_zone(subdomain, domain) build_structure(subdomain, domain) elif opt in ("-h", "--help"): usage() elif opt in ("-i", "--ip"): if len(args) < 2: usage() subdomain, domain = split_args(args[0]) ip = args[1] set_domain_ip(subdomain, domain, ip) elif opt in ("-l", "--list"): list_domains() elif opt in ("-u", "--user"): if len(args) < 2: usage() subdomain, domain = split_args(args[0]) user = args[1] set_domain_user(subdomain, domain, user) elif opt in ("-v", "--vhost"): if len(args) < 1: usage() subdomain, domain = split_args(args[0]) build_vhost(subdomain, domain) elif opt in ("-z", "--zone"): if len(args) < 1: usage() subdomain, domain = split_args(args[0]) build_zone(subdomain, domain) elif opt == '': usage() sys.exit(0) def split_args(args): """Splits the subdomain from a domain and returns both.""" if args.count(".") < 2: subdomain, domain = ("", args) else: subdomain, domain = args.split(".", 1) return subdomain, domain def add_domain(subdomain, domain, user, email, ip): """Adds a domain (or subdomain) to the db.""" try: db = sqlite3.connect(database) db.execute(""" insert into store (user, subdomain, domain, email, ip) values (?, ?, ?, ?, ?) """, (user.lower(), subdomain.lower(), domain.lower(), email.lower(), ip.lower(),)) db.commit() except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def create_db(): """Creates the database for tracking control info.""" try: db = sqlite3.connect(database) db.execute(""" create table store ( id integer primary key, user text not null, subdomain text not null, domain text not null, email text not null, ip text not null ) """) except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def delete_user(user): """Drops a user entry, and all associated domains, from the database.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select subdomain, domain from store where user = ? """, (user,)).fetchall() if len(resultset) == 0: print "User '%s' does not exist." % user sys.exit(1) print "WARNING! You are about to delete the user '%s' and the following domains:" for subdomain, domain in resultset: if subdomain != '': domain = subdomain + "." + domain print domain answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" delete from store where user = ? """, (user,)) db.commit() else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def delete_domain(domain): """Drops a domain (or subdomain), and all associated subdomains, from the database.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where domain = ? """, (domain,)).fetchall() if len(resultset) == 0: print "Domain '%s' does not exist." % domain sys.exit(1) resultset = db.execute(""" select subdomain, domain from store where domain = ? and subdomain != '' """, (domain,)).fetchall() print "WARNING! You are about to delete the domain '%s' and the following subdomains:" % domain for subdomain, domain in resultset: print "%s.%s" % (subdomain, domain) answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" delete from store where domain = ? """, (domain,)) db.commit() else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def delete_subdomain(subdomain, domain): """Drops a subdomain from the database.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where domain = ? and subdomain = ? """, (domain, subdomain,)).fetchall() if len(resultset) == 0: print "Subdomain '%s.%s' does not exist." % (subdomain, domain) sys.exit(1) print "WARNING! You are about to delete the subdomain '%s.%s'." % (subdomain, domain) answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" delete from store where domain = ? and subdomain = ? """, (domain, subdomain,)) else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def list_domains(): """Prints the stored domains in a visually helpful manner.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select user, subdomain, domain, ip, email from store """).fetchall() print "%s%s%s%s" % ("user".ljust(16), "email".ljust(32), "domain".ljust(32), "ip") for user, subdomain, domain, ip, email in resultset: if subdomain != "": domain = subdomain + "." + domain print "%s%s%s%s" % (user.ljust(16), email.ljust(32), domain.ljust(32), ip) except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def build_zone(subdomain, domain): """Builds the zonefile from a template.""" zone_file = "%s.zone" % domain try: db = sqlite3.connect(database) resultset = db.execute(""" select user from store where domain = ? and subdomain = '' """, (domain,)).fetchall() user = resultset[0][0] resultset = db.execute(""" select subdomain, ip from store where domain = ? and subdomain != '' """, (domain,)).fetchall() except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) if os.path.isfile(zone_file): shutil.copy(zone_file, zone_file + ".old") template = open("zone_template.txt", "r") zone = open(zone_file, "w") line = template.readline() while line: line = line.replace("[user]", user) line = line.replace("[domain]", domain) line = line.replace("[serial]", date.strftime(datetime.today(), format="%Y%m%d%M")) zone.write(line) line = template.readline() zone.seek(0, os.SEEK_END) for subdomain, ip in resultset: if ip == "cname": zone.write("%sIN CNAME %s.\n" % (subdomain.ljust(32), domain)) else: zone.write("%sIN A %s\n" % (subdomain.ljust(32), ip)) zone.close() template.close() def set_domain_user(subdomain, domain, user): """Set the user associated with a given domain.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where domain = ? and subdomain = ? """, (domain, subdomain,)).fetchall() if len(resultset) == 0: if subdomain: print "Subdomain '%s.%s' does not exist." % (subdomain, domain) else: print "Domain '%s' does not exist." % (domain) sys.exit(1) resultset = db.execute(""" update store set user = ? where domain = ? and subdomain = ? """, (email, domain, subdomain,)) db.commit() except sqlite2.OperationalError as e: print "error: %s" % e sys.exit(1) def build_vhost(subdomain, domain): """Build the apache vhost file from a template.""" if subdomain: vhost_file = "%s.%s" % (subdomain, domain) else: vhost_file = domain try: db = sqlite3.connect(database) resultset = db.execute(""" select user from store where domain = ? and subdomain = ? limit 1 """, (domain, subdomain,)).fetchall() user = resultset[0][0] except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) if os.path.isfile(vhost_file): shutil.copy(vhost_file, vhost_file + ".old") template = open("vhost_template.txt", "r") vhost = open(vhost_file, "w") line = template.readline() while line: if not subdomain: line = line.replace("[subdomain].[domain]", domain) line = line.replace("[ServerAlias]", "ServerAlias www.%s" % domain) else: line = line.replace("[ServerAlias]", "") line = line.replace("[user]", user) line = line.replace("[domain]", domain) line = line.replace("[subdomain]", subdomain) line = line.replace("//", "/") vhost.write(line) line = template.readline() vhost.close() template.close() def build_structure(subdomain, domain): """Build the dir structure for hosting the domain or subdomain.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select user from store where domain = ? and subdomain = ? limit 1 """, (domain, subdomain,)).fetchall() if len(resultset) == 0: if subdomain: print "Subdomain '%s.%s' does not exist." % (subdomain, domain) else: print "Domain '%s' does not exist." % domain sys.exit(1) user = resultset[0][0] if not subdomain: os.makedirs(name="%s/%s/%s/public_html" % (homedir, user, domain), mode=0755) os.makedirs(name="%s/%s/%s/cgi-bin" % (homedir, user, domain), mode=0755) else: os.makedirs(name="%s/%s/%s/%s/public_html" % (homedir, user, domain, subdomain), mode=0755) os.makedirs(name="%s/%s/%s/%s/cgi-bin" % (homedir, user, domain, subdomain), mode=0755) except OSError as exc: if exc.errno == errno.EEXIST: pass else: raise except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def set_domain_email(subdomain, domain, email): """Set the email associated with a given domain.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select 1 from store where domain = ? and subdomain = ? limit 1 """, (domain, subdomain,)).fetchall() if len(resultset) == 0: if subdomain: print "Subdomain '%s.%s' does not exist." % (subdomain, domain) else: print "Domain '%s' does not exist." % (domain) sys.exit(1) resultset = db.execute(""" update store set email = ? where domain = ? and subdomain = ? """, (email, domain, subdomain,)) db.commit() except sqlite2.OperationalError as e: print "error: %s" % e sys.exit(1) def set_user_email(user, email): """Set the email associated with a given user.""" try: db = sqlite3.connect(database) resultset = db.execute(""" select subdomain, domain from store where user = ? """, (user,)).fetchall() if len(resultset) == 0: print "User '%s' does not exist." % (user) print "WARNING! You are about to change the email address for user '%s'." print "This will affect the following domains:" for subdomain, domain in resultset: if subdomain != '': domain = subdomain + "." + domain print domain answer = raw_input("Are you sure that you want to do this? (y/N): ") if answer.lower() == "y" or answer.lower() == "yes": db.execute(""" update store set email = ? where user = ? """, (email, user,)) db.commit() else: print "Aborted." except sqlite3.OperationalError as e: print "error: %s" % e sys.exit(1) def usage(): """Print usage info.""" print "domainctl